about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2023-06-02 10:03:49 +0200
committerRalf Jung <post@ralfj.de>2023-06-02 10:03:49 +0200
commitc5aebfb9348277639b0877eb83995dfd1bd2ff23 (patch)
treed54ef5d9706906a3b6bd2aa5337bd32d03b4112e
parent777db72b08f316345cffde2fc83478668b9da7cf (diff)
parent33c3d101280c8eb3cd8af421bfb56a8afcc3881d (diff)
downloadrust-c5aebfb9348277639b0877eb83995dfd1bd2ff23.tar.gz
rust-c5aebfb9348277639b0877eb83995dfd1bd2ff23.zip
Merge from rustc
-rw-r--r--.github/workflows/ci.yml1
-rw-r--r--compiler/rustc_abi/src/lib.rs49
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs14
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs8
-rw-r--r--compiler/rustc_codegen_cranelift/src/common.rs16
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/consts.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/context.rs15
-rw-r--r--compiler/rustc_codegen_gcc/src/type_of.rs3
-rw-r--r--compiler/rustc_codegen_llvm/messages.ftl8
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs19
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs17
-rw-r--r--compiler/rustc_codegen_llvm/src/errors.rs12
-rw-r--r--compiler/rustc_codegen_llvm/src/type_of.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs13
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/debuginfo.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs13
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs49
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs68
-rw-r--r--compiler/rustc_const_eval/messages.ftl397
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs280
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs100
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs119
-rw-r--r--compiler/rustc_const_eval/src/const_eval/mod.rs52
-rw-r--r--compiler/rustc_const_eval/src/errors.rs676
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs20
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs45
-rw-r--r--compiler/rustc_const_eval/src/interpret/intern.rs27
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs75
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs63
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs51
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs217
-rw-r--r--compiler/rustc_const_eval/src/lib.rs7
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs133
-rw-r--r--compiler/rustc_const_eval/src/util/check_validity_requirement.rs8
-rw-r--r--compiler/rustc_data_structures/src/sync.rs11
-rw-r--r--compiler/rustc_error_messages/src/lib.rs4
-rw-r--r--compiler/rustc_errors/messages.ftl6
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs4
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs23
-rw-r--r--compiler/rustc_feature/src/accepted.rs4
-rw-r--r--compiler/rustc_feature/src/active.rs12
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs4
-rw-r--r--compiler/rustc_feature/src/removed.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs111
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs12
-rw-r--r--compiler/rustc_lint/messages.ftl2
-rw-r--r--compiler/rustc_lint/src/builtin.rs12
-rw-r--r--compiler/rustc_lint/src/cast_ref_to_mut.rs72
-rw-r--r--compiler/rustc_lint/src/lib.rs3
-rw-r--r--compiler/rustc_lint/src/lints.rs5
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs38
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs16
-rw-r--r--compiler/rustc_macros/src/diagnostics/subdiagnostic.rs23
-rw-r--r--compiler/rustc_macros/src/diagnostics/utils.rs27
-rw-r--r--compiler/rustc_metadata/src/creader.rs20
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs21
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs8
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs1
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs1
-rw-r--r--compiler/rustc_metadata/src/rmeta/table.rs2
-rw-r--r--compiler/rustc_middle/messages.ftl35
-rw-r--r--compiler/rustc_middle/src/error.rs55
-rw-r--r--compiler/rustc_middle/src/lib.rs3
-rw-r--r--compiler/rustc_middle/src/middle/limits.rs11
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs48
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs444
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs31
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs3
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs137
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs2
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs3
-rw-r--r--compiler/rustc_middle/src/query/mod.rs12
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs9
-rw-r--r--compiler/rustc_middle/src/ty/context.rs10
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs75
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs6
-rw-r--r--compiler/rustc_middle/src/ty/util.rs22
-rw-r--r--compiler/rustc_middle/src/ty/vtable.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_constant.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs1
-rw-r--r--compiler/rustc_mir_build/src/lib.rs1
-rw-r--r--compiler/rustc_mir_build/src/thir/constant.rs18
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs311
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs33
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs124
-rw-r--r--compiler/rustc_mir_transform/src/const_goto.rs2
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs54
-rw-r--r--compiler/rustc_mir_transform/src/const_prop_lint.rs6
-rw-r--r--compiler/rustc_mir_transform/src/errors.rs11
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs5
-rw-r--r--compiler/rustc_mir_transform/src/required_consts.rs4
-rw-r--r--compiler/rustc_mir_transform/src/separate_const_switch.rs2
-rw-r--r--compiler/rustc_mir_transform/src/sroa.rs50
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs76
-rw-r--r--compiler/rustc_monomorphize/src/partitioning.rs7
-rw-r--r--compiler/rustc_passes/src/layout_test.rs9
-rw-r--r--compiler/rustc_session/src/parse.rs1
-rw-r--r--compiler/rustc_session/src/session.rs2
-rw-r--r--compiler/rustc_span/src/hygiene.rs4
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs17
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs11
-rw-r--r--compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs2
-rw-r--r--compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs2
-rw-r--r--library/alloc/src/alloc.rs2
-rw-r--r--library/alloc/src/string.rs2
-rw-r--r--library/core/src/convert/mod.rs3
-rw-r--r--library/core/src/ffi/c_str.rs6
-rw-r--r--library/core/src/ffi/mod.rs2
-rw-r--r--library/core/src/hash/mod.rs2
-rw-r--r--library/core/src/intrinsics.rs33
-rw-r--r--library/core/src/marker.rs3
-rw-r--r--library/core/src/mem/mod.rs3
-rw-r--r--library/core/src/num/nonzero.rs28
-rw-r--r--library/core/src/ptr/const_ptr.rs15
-rw-r--r--library/core/src/ptr/mod.rs5
-rw-r--r--library/core/src/ptr/mut_ptr.rs26
-rw-r--r--library/core/src/slice/mod.rs2
-rw-r--r--library/core/src/tuple.rs4
-rw-r--r--library/core/tests/clone.rs2
-rw-r--r--library/core/tests/lib.rs2
-rw-r--r--library/core/tests/mem.rs11
-rw-r--r--library/std/Cargo.toml12
-rw-r--r--library/std/src/os/windows/io/handle.rs6
-rw-r--r--library/std/src/os/windows/io/socket.rs6
-rw-r--r--library/std/src/sys/wasi/fd.rs6
-rw-r--r--library/std/src/sys/wasi/fs.rs4
-rw-r--r--library/std/src/sys/windows/stdio.rs7
-rw-r--r--library/std/src/sys/windows/stdio/tests.rs6
-rw-r--r--library/std/tests/common/mod.rs8
-rw-r--r--src/bootstrap/bootstrap.py21
-rw-r--r--src/bootstrap/dist.rs3
-rw-r--r--src/bootstrap/metadata.rs3
-rw-r--r--src/bootstrap/test.rs17
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile2
-rwxr-xr-xsrc/ci/docker/run.sh1
-rw-r--r--src/ci/github-actions/ci.yml1
-rw-r--r--src/ci/stage-build.py15
-rw-r--r--src/doc/unstable-book/src/language-features/const-eval-limit.md7
-rwxr-xr-xsrc/etc/pre-push.sh2
-rw-r--r--src/librustdoc/html/markdown.rs15
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css12
-rw-r--r--src/librustdoc/html/static/js/main.js148
-rw-r--r--src/stage0.json806
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_ref_to_mut.rs26
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/mod.rs38
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/renamed_lints.rs1
-rw-r--r--src/tools/clippy/tests/ui/cast_ref_to_mut.rs31
-rw-r--r--src/tools/clippy/tests/ui/cast_ref_to_mut.stderr22
-rw-r--r--src/tools/clippy/tests/ui/modulo_one.stderr6
-rw-r--r--src/tools/clippy/tests/ui/rename.fixed2
-rw-r--r--src/tools/clippy/tests/ui/rename.rs2
-rw-r--r--src/tools/clippy/tests/ui/rename.stderr106
-rw-r--r--src/tools/compiletest/src/runtest.rs47
-rw-r--r--src/tools/miri/src/diagnostics.rs68
-rw-r--r--src/tools/miri/src/eval.rs5
-rw-r--r--src/tools/miri/src/helpers.rs4
-rw-r--r--src/tools/miri/src/lib.rs1
-rw-r--r--src/tools/miri/tests/fail/intrinsics/copy_overlapping.rs2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/copy_overlapping.stderr4
-rw-r--r--src/tools/miri/tests/fail/intrinsics/ptr_offset_from_oob.stderr4
-rw-r--r--src/tools/miri/tests/fail/modifying_constants.rs2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/shr_frozen_violation1.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/builtin_attr.rs4
-rwxr-xr-xsrc/tools/rust-installer/combine-installers.sh4
-rwxr-xr-xsrc/tools/rust-installer/gen-installer.sh4
-rwxr-xr-xsrc/tools/rust-installer/make-tarballs.sh4
-rw-r--r--src/tools/tidy/src/main.rs6
-rw-r--r--tests/assembly/asm/mips-types.rs12
-rw-r--r--tests/codegen/const_scalar_pair.rs2
-rw-r--r--tests/codegen/intrinsics/transmute.rs75
-rw-r--r--tests/codegen/issues/issue-105386-ub-in-debuginfo.rs7
-rw-r--r--tests/incremental/hashes/match_expressions.rs3
-rw-r--r--tests/incremental/issue-101518.rs13
-rw-r--r--tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir2
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff96
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir104
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff96
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir104
-rw-r--r--tests/mir-opt/pre-codegen/chained_comparison.bitand.PreCodegen.after.mir84
-rw-r--r--tests/mir-opt/pre-codegen/chained_comparison.naive.PreCodegen.after.mir127
-rw-r--r--tests/mir-opt/pre-codegen/chained_comparison.returning.PreCodegen.after.mir126
-rw-r--r--tests/mir-opt/pre-codegen/chained_comparison.rs51
-rw-r--r--tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir144
-rw-r--r--tests/mir-opt/pre-codegen/checked_ops.rs17
-rw-r--r--tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir64
-rw-r--r--tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir102
-rw-r--r--tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir118
-rw-r--r--tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir91
-rw-r--r--tests/mir-opt/pre-codegen/loops.rs37
-rw-r--r--tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir83
-rw-r--r--tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir10
-rw-r--r--tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir20
-rw-r--r--tests/mir-opt/pre-codegen/slice_filter.rs15
-rw-r--r--tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir228
-rw-r--r--tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir92
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.mir16
-rw-r--r--tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.mir119
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.mir213
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.mir15
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.mir155
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.mir15
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.rs15
-rw-r--r--tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff78
-rw-r--r--tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff21
-rw-r--r--tests/mir-opt/slice_filter.rs20
-rw-r--r--tests/mir-opt/slice_filter.variant_a-{closure#0}.CopyProp.diff279
-rw-r--r--tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff165
-rw-r--r--tests/mir-opt/slice_filter.variant_a-{closure#0}.ReferencePropagation.diff267
-rw-r--r--tests/mir-opt/slice_filter.variant_b-{closure#0}.CopyProp.diff139
-rw-r--r--tests/mir-opt/slice_filter.variant_b-{closure#0}.DestinationPropagation.diff109
-rw-r--r--tests/mir-opt/slice_filter.variant_b-{closure#0}.ReferencePropagation.diff103
-rw-r--r--tests/rustdoc-gui/codeblock-tooltip.goml2
-rw-r--r--tests/rustdoc-gui/notable-trait.goml19
-rw-r--r--tests/rustdoc-gui/theme-in-history.goml6
-rw-r--r--tests/rustdoc/intra-doc/issue-108459.rs37
-rw-r--r--tests/rustdoc/intra-doc/prim-precedence.rs2
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs4
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr8
-rw-r--r--tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs12
-rw-r--r--tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr14
-rw-r--r--tests/ui/chalkify/bugs/async.stderr13
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-80742.stderr4
-rw-r--r--tests/ui/const-generics/issues/issue-100313.rs1
-rw-r--r--tests/ui/const-generics/issues/issue-100313.stderr12
-rw-r--r--tests/ui/const-ptr/forbidden_slices.stderr10
-rw-r--r--tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr2
-rw-r--r--tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.rs4
-rw-r--r--tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.stderr4
-rw-r--r--tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs4
-rw-r--r--tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr6
-rw-r--r--tests/ui/consts/const-eval/heap/dealloc_intrinsic_incorrect_layout.stderr2
-rw-r--r--tests/ui/consts/const-eval/infinite_loop.rs4
-rw-r--r--tests/ui/consts/const-eval/infinite_loop.stderr23
-rw-r--r--tests/ui/consts/const-eval/issue-52475.rs3
-rw-r--r--tests/ui/consts/const-eval/issue-52475.stderr22
-rw-r--r--tests/ui/consts/const-eval/issue-70723.rs2
-rw-r--r--tests/ui/consts/const-eval/issue-70723.stderr14
-rw-r--r--tests/ui/consts/const-eval/raw-bytes.32bit.stderr14
-rw-r--r--tests/ui/consts/const-eval/raw-bytes.64bit.stderr14
-rw-r--r--tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.rs2
-rw-r--r--tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr19
-rw-r--r--tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.rs5
-rw-r--r--tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.stderr27
-rw-r--r--tests/ui/consts/const-eval/stable-metric/ctfe-recursion.rs3
-rw-r--r--tests/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr24
-rw-r--r--tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.allow.stderr19
-rw-r--r--tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.rs12
-rw-r--r--tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.stderr24
-rw-r--r--tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr62
-rw-r--r--tests/ui/consts/const-eval/ub-enum.32bit.stderr4
-rw-r--r--tests/ui/consts/const-eval/ub-enum.64bit.stderr4
-rw-r--r--tests/ui/consts/const-eval/ub-uninhabit.stderr4
-rw-r--r--tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr2
-rw-r--r--tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr2
-rw-r--r--tests/ui/consts/const_limit/const_eval_limit_not_reached.rs20
-rw-r--r--tests/ui/consts/const_limit/const_eval_limit_overflow.rs15
-rw-r--r--tests/ui/consts/const_limit/const_eval_limit_overflow.stderr10
-rw-r--r--tests/ui/consts/const_limit/const_eval_limit_reached.rs16
-rw-r--r--tests/ui/consts/const_limit/const_eval_limit_reached.stderr12
-rw-r--r--tests/ui/consts/const_limit/feature-gate-const_eval_limit.rs14
-rw-r--r--tests/ui/consts/const_limit/feature-gate-const_eval_limit.stderr12
-rw-r--r--tests/ui/consts/issue-64506.stderr2
-rw-r--r--tests/ui/consts/issue-83182.stderr4
-rw-r--r--tests/ui/consts/issue-miri-1910.stderr4
-rw-r--r--tests/ui/consts/miri_unleashed/assoc_const.stderr2
-rw-r--r--tests/ui/consts/miri_unleashed/raw_mutable_const.rs2
-rw-r--r--tests/ui/consts/miri_unleashed/raw_mutable_const.stderr4
-rw-r--r--tests/ui/consts/missing_span_in_backtrace.stderr4
-rw-r--r--tests/ui/consts/offset_from_ub.stderr14
-rw-r--r--tests/ui/consts/raw-ptr-const.rs2
-rw-r--r--tests/ui/consts/raw-ptr-const.stderr4
-rw-r--r--tests/ui/dyn-star/param-env-infer.next.stderr35
-rw-r--r--tests/ui/impl-trait/auto-trait-leak.stderr70
-rw-r--r--tests/ui/impl-trait/multiple-defining-usages-in-body.rs2
-rw-r--r--tests/ui/impl-trait/multiple-defining-usages-in-body.stderr10
-rw-r--r--tests/ui/inline-const/elided-lifetime-being-infer-vars.rs11
-rw-r--r--tests/ui/lint/cast_ref_to_mut.rs50
-rw-r--r--tests/ui/lint/cast_ref_to_mut.stderr64
-rw-r--r--tests/ui/loops/dont-suggest-break-thru-item.rs55
-rw-r--r--tests/ui/loops/dont-suggest-break-thru-item.stderr55
-rw-r--r--tests/ui/match/issue-70972-dyn-trait.rs2
-rw-r--r--tests/ui/match/issue-70972-dyn-trait.stderr2
-rw-r--r--tests/ui/numbers-arithmetic/issue-8460-const.noopt.stderr12
-rw-r--r--tests/ui/numbers-arithmetic/issue-8460-const.opt.stderr12
-rw-r--r--tests/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr12
-rw-r--r--tests/ui/pattern/issue-72565.rs2
-rw-r--r--tests/ui/pattern/issue-72565.stderr2
-rw-r--r--tests/ui/statics/uninhabited-static.stderr4
-rw-r--r--tests/ui/suggestions/issue-88696.rs14
-rw-r--r--tests/ui/suggestions/issue-88696.stderr11
-rw-r--r--tests/ui/track-diagnostics/track6.stderr2
-rw-r--r--tests/ui/traits/new-solver/dont-remap-tait-substs.rs19
-rw-r--r--tests/ui/type-alias-impl-trait/cross_inference.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr11
-rw-r--r--triagebot.toml4
306 files changed, 6766 insertions, 4339 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b12a0b855e2..210ec72a11e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -578,6 +578,7 @@ jobs:
       actions: write
     name: "try - ${{ matrix.name }}"
     env:
+      DIST_TRY_BUILD: 1
       CI_JOB_NAME: "${{ matrix.name }}"
       CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse
       SCCACHE_BUCKET: rust-lang-ci-sccache2
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 43db66a3c28..2ee63c286ba 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -209,7 +209,7 @@ pub enum TargetDataLayoutErrors<'a> {
     InvalidAddressSpace { addr_space: &'a str, cause: &'a str, err: ParseIntError },
     InvalidBits { kind: &'a str, bit: &'a str, cause: &'a str, err: ParseIntError },
     MissingAlignment { cause: &'a str },
-    InvalidAlignment { cause: &'a str, err: String },
+    InvalidAlignment { cause: &'a str, err: AlignFromBytesError },
     InconsistentTargetArchitecture { dl: &'a str, target: &'a str },
     InconsistentTargetPointerWidth { pointer_size: u64, target: u32 },
     InvalidBitsSize { err: String },
@@ -640,30 +640,65 @@ impl fmt::Debug for Align {
     }
 }
 
+#[derive(Clone, Copy)]
+pub enum AlignFromBytesError {
+    NotPowerOfTwo(u64),
+    TooLarge(u64),
+}
+
+impl AlignFromBytesError {
+    pub fn diag_ident(self) -> &'static str {
+        match self {
+            Self::NotPowerOfTwo(_) => "not_power_of_two",
+            Self::TooLarge(_) => "too_large",
+        }
+    }
+
+    pub fn align(self) -> u64 {
+        let (Self::NotPowerOfTwo(align) | Self::TooLarge(align)) = self;
+        align
+    }
+}
+
+impl fmt::Debug for AlignFromBytesError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(self, f)
+    }
+}
+
+impl fmt::Display for AlignFromBytesError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            AlignFromBytesError::NotPowerOfTwo(align) => write!(f, "`{align}` is not a power of 2"),
+            AlignFromBytesError::TooLarge(align) => write!(f, "`{align}` is too large"),
+        }
+    }
+}
+
 impl Align {
     pub const ONE: Align = Align { pow2: 0 };
     pub const MAX: Align = Align { pow2: 29 };
 
     #[inline]
-    pub fn from_bits(bits: u64) -> Result<Align, String> {
+    pub fn from_bits(bits: u64) -> Result<Align, AlignFromBytesError> {
         Align::from_bytes(Size::from_bits(bits).bytes())
     }
 
     #[inline]
-    pub fn from_bytes(align: u64) -> Result<Align, String> {
+    pub fn from_bytes(align: u64) -> Result<Align, AlignFromBytesError> {
         // Treat an alignment of 0 bytes like 1-byte alignment.
         if align == 0 {
             return Ok(Align::ONE);
         }
 
         #[cold]
-        fn not_power_of_2(align: u64) -> String {
-            format!("`{}` is not a power of 2", align)
+        fn not_power_of_2(align: u64) -> AlignFromBytesError {
+            AlignFromBytesError::NotPowerOfTwo(align)
         }
 
         #[cold]
-        fn too_large(align: u64) -> String {
-            format!("`{}` is too large", align)
+        fn too_large(align: u64) -> AlignFromBytesError {
+            AlignFromBytesError::TooLarge(align)
         }
 
         let tz = align.trailing_zeros();
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 33f07c1d8fc..13e346b86bc 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -279,8 +279,18 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
         // HACK This bubble is required for this tests to pass:
         // nested-return-type2-tait2.rs
         // nested-return-type2-tait3.rs
-        let infcx =
-            self.tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bubble).build();
+        // FIXME(-Ztrait-solver=next): We probably should use `DefiningAnchor::Error`
+        // and prepopulate this `InferCtxt` with known opaque values, rather than
+        // using the `Bind` anchor here. For now it's fine.
+        let infcx = self
+            .tcx
+            .infer_ctxt()
+            .with_opaque_type_inference(if self.tcx.trait_solver_next() {
+                DefiningAnchor::Bind(def_id)
+            } else {
+                DefiningAnchor::Bubble
+            })
+            .build();
         let ocx = ObligationCtxt::new(&infcx);
         // Require the hidden type to be well-formed with only the generics of the opaque type.
         // Defining use functions may have more bounds than the opaque type, which is ok, as long as the
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 3b896f6540c..908ff3da5ca 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -188,9 +188,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
 
     // FIXME(-Ztrait-solver=next): A bit dubious that we're only registering
     // predefined opaques in the typeck root.
-    // FIXME(-Ztrait-solver=next): This is also totally wrong for TAITs, since
-    // the HIR typeck map defining usages back to their definition params,
-    // they won't actually match up with the usages in this body...
     if infcx.tcx.trait_solver_next() && !infcx.tcx.is_typeck_child(body.source.def_id()) {
         checker.register_predefined_opaques_in_new_solver();
     }
@@ -1042,10 +1039,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             .typeck(self.body.source.def_id().expect_local())
             .concrete_opaque_types
             .iter()
-            .map(|(&def_id, &hidden_ty)| {
-                let substs = ty::InternalSubsts::identity_for_item(self.infcx.tcx, def_id);
-                (ty::OpaqueTypeKey { def_id, substs }, hidden_ty)
-            })
+            .map(|(k, v)| (*k, *v))
             .collect();
 
         let renumbered_opaques = self.infcx.tcx.fold_regions(opaques, |_, _| {
diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs
index 67fd6d793e0..7243cf6da23 100644
--- a/compiler/rustc_codegen_cranelift/src/common.rs
+++ b/compiler/rustc_codegen_cranelift/src/common.rs
@@ -6,6 +6,7 @@ use rustc_index::IndexVec;
 use rustc_middle::ty::layout::{
     FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers,
 };
+use rustc_span::source_map::Spanned;
 use rustc_span::SourceFile;
 use rustc_target::abi::call::FnAbi;
 use rustc_target::abi::{Integer, Primitive};
@@ -495,25 +496,16 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> {
         fn_abi_request: FnAbiRequest<'tcx>,
     ) -> ! {
         if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
-            self.0.sess.span_fatal(span, err.to_string())
+            self.0.sess.emit_fatal(Spanned { span, node: err })
         } else {
             match fn_abi_request {
                 FnAbiRequest::OfFnPtr { sig, extra_args } => {
-                    span_bug!(
-                        span,
-                        "`fn_abi_of_fn_ptr({}, {:?})` failed: {}",
-                        sig,
-                        extra_args,
-                        err
-                    );
+                    span_bug!(span, "`fn_abi_of_fn_ptr({sig}, {extra_args:?})` failed: {err:?}");
                 }
                 FnAbiRequest::OfInstance { instance, extra_args } => {
                     span_bug!(
                         span,
-                        "`fn_abi_of_instance({}, {:?})` failed: {}",
-                        instance,
-                        extra_args,
-                        err
+                        "`fn_abi_of_instance({instance}, {extra_args:?})` failed: {err:?}"
                     );
                 }
             }
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 869344ce92d..f9ea0f00456 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -758,7 +758,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         assert_eq!(place.llextra.is_some(), place.layout.is_unsized());
 
         if place.layout.is_zst() {
-            return OperandRef::new_zst(self, place.layout);
+            return OperandRef::zero_sized(place.layout);
         }
 
         fn scalar_load_metadata<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, load: RValue<'gcc>, scalar: &abi::Scalar) {
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index 873f652e6f1..33e3b0baa92 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -24,7 +24,7 @@ fn set_global_alignment<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, gv: LValue<'gcc>
         match Align::from_bits(min) {
             Ok(min) => align = align.max(min),
             Err(err) => {
-                cx.sess().emit_err(InvalidMinimumAlignment { err });
+                cx.sess().emit_err(InvalidMinimumAlignment { err: err.to_string() });
             }
         }
     }
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index 661681bdb50..08507e19652 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -477,7 +477,7 @@ impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
     #[inline]
     fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
         if let LayoutError::SizeOverflow(_) = err {
-            self.sess().emit_fatal(respan(span, err))
+            self.sess().emit_fatal(respan(span, err.into_diagnostic()))
         } else {
             span_bug!(span, "failed to get layout for `{}`: {}", ty, err)
         }
@@ -499,21 +499,12 @@ impl<'gcc, 'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
         } else {
             match fn_abi_request {
                 FnAbiRequest::OfFnPtr { sig, extra_args } => {
-                    span_bug!(
-                        span,
-                        "`fn_abi_of_fn_ptr({}, {:?})` failed: {}",
-                        sig,
-                        extra_args,
-                        err
-                    );
+                    span_bug!(span, "`fn_abi_of_fn_ptr({sig}, {extra_args:?})` failed: {err:?}");
                 }
                 FnAbiRequest::OfInstance { instance, extra_args } => {
                     span_bug!(
                         span,
-                        "`fn_abi_of_instance({}, {:?})` failed: {}",
-                        instance,
-                        extra_args,
-                        err
+                        "`fn_abi_of_instance({instance}, {extra_args:?})` failed: {err:?}"
                     );
                 }
             }
diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs
index 5df8c1a209d..30a3fe67b85 100644
--- a/compiler/rustc_codegen_gcc/src/type_of.rs
+++ b/compiler/rustc_codegen_gcc/src/type_of.rs
@@ -159,8 +159,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
     fn is_gcc_immediate(&self) -> bool {
         match self.abi {
             Abi::Scalar(_) | Abi::Vector { .. } => true,
-            Abi::ScalarPair(..) => false,
-            Abi::Uninhabited | Abi::Aggregate { .. } => self.is_zst(),
+            Abi::ScalarPair(..) | Abi::Uninhabited | Abi::Aggregate { .. } => false,
         }
     }
 
diff --git a/compiler/rustc_codegen_llvm/messages.ftl b/compiler/rustc_codegen_llvm/messages.ftl
index 55622fdb20a..de1622951fe 100644
--- a/compiler/rustc_codegen_llvm/messages.ftl
+++ b/compiler/rustc_codegen_llvm/messages.ftl
@@ -20,8 +20,12 @@ codegen_llvm_error_writing_def_file =
 codegen_llvm_from_llvm_diag = {$message}
 
 codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message}
-codegen_llvm_invalid_minimum_alignment =
-    invalid minimum global alignment: {$err}
+
+codegen_llvm_invalid_minimum_alignment_not_power_of_two =
+    invalid minimum global alignment: {$align} is not power of 2
+
+codegen_llvm_invalid_minimum_alignment_too_large =
+    invalid minimum global alignment: {$align} is too large
 
 codegen_llvm_load_bitcode = failed to load bitcode of module "{$name}"
 codegen_llvm_load_bitcode_with_llvm_err = failed to load bitcode of module "{$name}": {$llvm_err}
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 4d0bcd53d15..5968e70b1cc 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -486,7 +486,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         assert_eq!(place.llextra.is_some(), place.layout.is_unsized());
 
         if place.layout.is_zst() {
-            return OperandRef::new_zst(self, place.layout);
+            return OperandRef::zero_sized(place.layout);
         }
 
         #[instrument(level = "trace", skip(bx))]
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 940358acde9..df52f50f86f 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -1,7 +1,9 @@
 use crate::base;
 use crate::common::{self, CodegenCx};
 use crate::debuginfo;
-use crate::errors::{InvalidMinimumAlignment, SymbolAlreadyDefined};
+use crate::errors::{
+    InvalidMinimumAlignmentNotPowerOfTwo, InvalidMinimumAlignmentTooLarge, SymbolAlreadyDefined,
+};
 use crate::llvm::{self, True};
 use crate::type_::Type;
 use crate::type_of::LayoutLlvmExt;
@@ -19,7 +21,9 @@ use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, Instance, Ty};
 use rustc_middle::{bug, span_bug};
 use rustc_session::config::Lto;
-use rustc_target::abi::{Align, HasDataLayout, Primitive, Scalar, Size, WrappingRange};
+use rustc_target::abi::{
+    Align, AlignFromBytesError, HasDataLayout, Primitive, Scalar, Size, WrappingRange,
+};
 use std::ops::Range;
 
 pub fn const_alloc_to_llvm<'ll>(cx: &CodegenCx<'ll, '_>, alloc: ConstAllocation<'_>) -> &'ll Value {
@@ -129,9 +133,14 @@ fn set_global_alignment<'ll>(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, mut align:
     if let Some(min) = cx.sess().target.min_global_align {
         match Align::from_bits(min) {
             Ok(min) => align = align.max(min),
-            Err(err) => {
-                cx.sess().emit_err(InvalidMinimumAlignment { err });
-            }
+            Err(err) => match err {
+                AlignFromBytesError::NotPowerOfTwo(align) => {
+                    cx.sess().emit_err(InvalidMinimumAlignmentNotPowerOfTwo { align });
+                }
+                AlignFromBytesError::TooLarge(align) => {
+                    cx.sess().emit_err(InvalidMinimumAlignmentTooLarge { align });
+                }
+            },
         }
     }
     unsafe {
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 83101a85435..ca0f771f5b9 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -969,9 +969,9 @@ impl<'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'_, 'tcx> {
     #[inline]
     fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
         if let LayoutError::SizeOverflow(_) = err {
-            self.sess().emit_fatal(Spanned { span, node: err })
+            self.sess().emit_fatal(Spanned { span, node: err.into_diagnostic() })
         } else {
-            span_bug!(span, "failed to get layout for `{}`: {}", ty, err)
+            span_bug!(span, "failed to get layout for `{ty}`: {err:?}")
         }
     }
 }
@@ -991,21 +991,12 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> {
         } else {
             match fn_abi_request {
                 FnAbiRequest::OfFnPtr { sig, extra_args } => {
-                    span_bug!(
-                        span,
-                        "`fn_abi_of_fn_ptr({}, {:?})` failed: {}",
-                        sig,
-                        extra_args,
-                        err
-                    );
+                    span_bug!(span, "`fn_abi_of_fn_ptr({sig}, {extra_args:?})` failed: {err:?}",);
                 }
                 FnAbiRequest::OfInstance { instance, extra_args } => {
                     span_bug!(
                         span,
-                        "`fn_abi_of_instance({}, {:?})` failed: {}",
-                        instance,
-                        extra_args,
-                        err
+                        "`fn_abi_of_instance({instance}, {extra_args:?})` failed: {err:?}",
                     );
                 }
             }
diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs
index 6a9173ab450..44869ced1ae 100644
--- a/compiler/rustc_codegen_llvm/src/errors.rs
+++ b/compiler/rustc_codegen_llvm/src/errors.rs
@@ -50,9 +50,15 @@ pub(crate) struct SymbolAlreadyDefined<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_llvm_invalid_minimum_alignment)]
-pub(crate) struct InvalidMinimumAlignment {
-    pub err: String,
+#[diag(codegen_llvm_invalid_minimum_alignment_not_power_of_two)]
+pub(crate) struct InvalidMinimumAlignmentNotPowerOfTwo {
+    pub align: u64,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_llvm_invalid_minimum_alignment_too_large)]
+pub(crate) struct InvalidMinimumAlignmentTooLarge {
+    pub align: u64,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs
index e264ce78f0d..a493c9c0548 100644
--- a/compiler/rustc_codegen_llvm/src/type_of.rs
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -198,8 +198,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
     fn is_llvm_immediate(&self) -> bool {
         match self.abi {
             Abi::Scalar(_) | Abi::Vector { .. } => true,
-            Abi::ScalarPair(..) => false,
-            Abi::Uninhabited | Abi::Aggregate { .. } => self.is_zst(),
+            Abi::ScalarPair(..) | Abi::Uninhabited | Abi::Aggregate { .. } => false,
         }
     }
 
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 15c7847155d..242d209b684 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -295,7 +295,7 @@ pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             let (base, info) = match bx.load_operand(src).val {
                 OperandValue::Pair(base, info) => unsize_ptr(bx, base, src_ty, dst_ty, Some(info)),
                 OperandValue::Immediate(base) => unsize_ptr(bx, base, src_ty, dst_ty, None),
-                OperandValue::Ref(..) => bug!(),
+                OperandValue::Ref(..) | OperandValue::ZeroSized => bug!(),
             };
             OperandValue::Pair(base, info).store(bx, dst);
         }
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 6297f91341d..e91f7b86e5e 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -93,8 +93,7 @@ fn push_debuginfo_type_name<'tcx>(
                     Err(e) => {
                         // Computing the layout can still fail here, e.g. if the target architecture
                         // cannot represent the type. See https://github.com/rust-lang/rust/issues/94961.
-                        // FIXME: migrate once `rustc_middle::mir::interpret::InterpError` is translatable.
-                        tcx.sess.fatal(format!("{}", e));
+                        tcx.sess.emit_fatal(e.into_diagnostic());
                     }
                 }
             } else {
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 3f0b64b1103..e0cb26d3ba8 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1,5 +1,5 @@
 use super::operand::OperandRef;
-use super::operand::OperandValue::{Immediate, Pair, Ref};
+use super::operand::OperandValue::{Immediate, Pair, Ref, ZeroSized};
 use super::place::PlaceRef;
 use super::{CachedLlbb, FunctionCx, LocalRef};
 
@@ -427,6 +427,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         assert_eq!(align, op.layout.align.abi, "return place is unaligned!");
                         llval
                     }
+                    ZeroSized => bug!("ZST return value shouldn't be in PassMode::Cast"),
                 };
                 let ty = bx.cast_backend_type(cast_ty);
                 let addr = bx.pointercast(llslot, bx.type_ptr_to(ty));
@@ -1386,6 +1387,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     (llval, align, true)
                 }
             }
+            ZeroSized => match arg.mode {
+                PassMode::Indirect { .. } => {
+                    // Though `extern "Rust"` doesn't pass ZSTs, some ABIs pass
+                    // a pointer for `repr(C)` structs even when empty, so get
+                    // one from an `alloca` (which can be left uninitialized).
+                    let scratch = PlaceRef::alloca(bx, arg.layout);
+                    (scratch.llval, scratch.align, true)
+                }
+                _ => bug!("ZST {op:?} wasn't ignored, but was passed with abi {arg:?}"),
+            },
         };
 
         if by_ref && !arg.is_indirect() {
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index bba2800fb05..4f79c6a3d82 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -352,6 +352,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         bx.set_var_name(a, &(name.clone() + ".0"));
                         bx.set_var_name(b, &(name.clone() + ".1"));
                     }
+                    OperandValue::ZeroSized => {
+                        // These never have a value to talk about
+                    }
                 },
                 LocalRef::PendingOperand => {}
             }
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 00414003202..2809ec2deb5 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -129,16 +129,13 @@ enum LocalRef<'tcx, V> {
     PendingOperand,
 }
 
-impl<'a, 'tcx, V: CodegenObject> LocalRef<'tcx, V> {
-    fn new_operand<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
-        bx: &mut Bx,
-        layout: TyAndLayout<'tcx>,
-    ) -> LocalRef<'tcx, V> {
+impl<'tcx, V: CodegenObject> LocalRef<'tcx, V> {
+    fn new_operand(layout: TyAndLayout<'tcx>) -> LocalRef<'tcx, V> {
         if layout.is_zst() {
             // Zero-size temporaries aren't always initialized, which
             // doesn't matter because they don't contain data, but
             // we need something in the operand.
-            LocalRef::Operand(OperandRef::new_zst(bx, layout))
+            LocalRef::Operand(OperandRef::zero_sized(layout))
         } else {
             LocalRef::PendingOperand
         }
@@ -249,7 +246,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
                 }
             } else {
                 debug!("alloc: {:?} -> operand", local);
-                LocalRef::new_operand(&mut start_bx, layout)
+                LocalRef::new_operand(layout)
             }
         };
 
@@ -355,7 +352,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
                 let local = |op| LocalRef::Operand(op);
                 match arg.mode {
                     PassMode::Ignore => {
-                        return local(OperandRef::new_zst(bx, arg.layout));
+                        return local(OperandRef::zero_sized(arg.layout));
                     }
                     PassMode::Direct(_) => {
                         let llarg = bx.get_param(llarg_idx);
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 4000c9540ce..31c293d7c29 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -45,6 +45,14 @@ pub enum OperandValue<V> {
     /// as returned by [`LayoutTypeMethods::scalar_pair_element_backend_type`]
     /// with `immediate: true`.
     Pair(V, V),
+    /// A value taking no bytes, and which therefore needs no LLVM value at all.
+    ///
+    /// If you ever need a `V` to pass to something, get a fresh poison value
+    /// from [`ConstMethods::const_poison`].
+    ///
+    /// An `OperandValue` *must* be this variant for any type for which
+    /// `is_zst` on its `Layout` returns `true`.
+    ZeroSized,
 }
 
 /// An `OperandRef` is an "SSA" reference to a Rust value, along with
@@ -71,15 +79,9 @@ impl<V: CodegenObject> fmt::Debug for OperandRef<'_, V> {
 }
 
 impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
-    pub fn new_zst<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
-        bx: &mut Bx,
-        layout: TyAndLayout<'tcx>,
-    ) -> OperandRef<'tcx, V> {
+    pub fn zero_sized(layout: TyAndLayout<'tcx>) -> OperandRef<'tcx, V> {
         assert!(layout.is_zst());
-        OperandRef {
-            val: OperandValue::Immediate(bx.const_poison(bx.immediate_backend_type(layout))),
-            layout,
-        }
+        OperandRef { val: OperandValue::ZeroSized, layout }
     }
 
     pub fn from_const<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
@@ -97,7 +99,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
                 let llval = bx.scalar_to_backend(x, scalar, bx.immediate_backend_type(layout));
                 OperandValue::Immediate(llval)
             }
-            ConstValue::ZeroSized => return OperandRef::new_zst(bx, layout),
+            ConstValue::ZeroSized => return OperandRef::zero_sized(layout),
             ConstValue::Slice { data, start, end } => {
                 let Abi::ScalarPair(a_scalar, _) = layout.abi else {
                     bug!("from_const: invalid ScalarPair layout: {:#?}", layout);
@@ -178,7 +180,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
                 );
                 OperandRef { val: OperandValue::Pair(a_val, b_val), layout }
             }
-            _ if layout.is_zst() => OperandRef::new_zst(bx, layout),
+            _ if layout.is_zst() => OperandRef::zero_sized(layout),
             _ => {
                 // Neither a scalar nor scalar pair. Load from a place
                 let init = bx.const_data_from_alloc(alloc);
@@ -216,6 +218,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
             OperandValue::Immediate(llptr) => (llptr, None),
             OperandValue::Pair(llptr, llextra) => (llptr, Some(llextra)),
             OperandValue::Ref(..) => bug!("Deref of by-Ref operand {:?}", self),
+            OperandValue::ZeroSized => bug!("Deref of ZST operand {:?}", self),
         };
         let layout = cx.layout_of(projected_ty);
         PlaceRef { llval: llptr, llextra, layout, align: layout.align.abi }
@@ -273,9 +276,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
 
         let mut val = match (self.val, self.layout.abi) {
             // If the field is ZST, it has no data.
-            _ if field.is_zst() => {
-                return OperandRef::new_zst(bx, field);
-            }
+            _ if field.is_zst() => OperandValue::ZeroSized,
 
             // Newtype of a scalar, scalar pair or vector.
             (OperandValue::Immediate(_) | OperandValue::Pair(..), _)
@@ -306,6 +307,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
         };
 
         match (&mut val, field.abi) {
+            (OperandValue::ZeroSized, _) => {}
             (
                 OperandValue::Immediate(llval),
                 Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. },
@@ -359,8 +361,8 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
 impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
     /// Returns an `OperandValue` that's generally UB to use in any way.
     ///
-    /// Depending on the `layout`, returns an `Immediate` or `Pair` containing
-    /// poison value(s), or a `Ref` containing a poison pointer.
+    /// Depending on the `layout`, returns `ZeroSized` for ZSTs, an `Immediate` or
+    /// `Pair` containing poison value(s), or a `Ref` containing a poison pointer.
     ///
     /// Supports sized types only.
     pub fn poison<Bx: BuilderMethods<'a, 'tcx, Value = V>>(
@@ -368,7 +370,9 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
         layout: TyAndLayout<'tcx>,
     ) -> OperandValue<V> {
         assert!(layout.is_sized());
-        if bx.cx().is_backend_immediate(layout) {
+        if layout.is_zst() {
+            OperandValue::ZeroSized
+        } else if bx.cx().is_backend_immediate(layout) {
             let ibty = bx.cx().immediate_backend_type(layout);
             OperandValue::Immediate(bx.const_poison(ibty))
         } else if bx.cx().is_backend_scalar_pair(layout) {
@@ -421,12 +425,11 @@ impl<'a, 'tcx, V: CodegenObject> OperandValue<V> {
         flags: MemFlags,
     ) {
         debug!("OperandRef::store: operand={:?}, dest={:?}", self, dest);
-        // Avoid generating stores of zero-sized values, because the only way to have a zero-sized
-        // value is through `undef`, and store itself is useless.
-        if dest.layout.is_zst() {
-            return;
-        }
         match self {
+            OperandValue::ZeroSized => {
+                // Avoid generating stores of zero-sized values, because the only way to have a zero-sized
+                // value is through `undef`/`poison`, and the store itself is useless.
+            }
             OperandValue::Ref(r, None, source_align) => {
                 if flags.contains(MemFlags::NONTEMPORAL) {
                     // HACK(nox): This is inefficient but there is no nontemporal memcpy.
@@ -527,7 +530,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                             // checks in `codegen_consume` and `extract_field`.
                             let elem = o.layout.field(bx.cx(), 0);
                             if elem.is_zst() {
-                                o = OperandRef::new_zst(bx, elem);
+                                o = OperandRef::zero_sized(elem);
                             } else {
                                 return None;
                             }
@@ -561,7 +564,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
         // ZSTs don't require any actual memory access.
         if layout.is_zst() {
-            return OperandRef::new_zst(bx, layout);
+            return OperandRef::zero_sized(layout);
         }
 
         if let Some(o) = self.maybe_codegen_consume_direct(bx, place_ref) {
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 0255b660380..5241a5aee00 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -70,6 +70,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     OperandValue::Ref(_, Some(_), _) => {
                         bug!("unsized coercion on an unsized rvalue");
                     }
+                    OperandValue::ZeroSized => {
+                        bug!("unsized coercion on a ZST rvalue");
+                    }
                 }
             }
 
@@ -165,11 +168,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         }
 
         match src.val {
-            OperandValue::Ref(..) => {
+            OperandValue::Ref(..) | OperandValue::ZeroSized => {
                 span_bug!(
                     self.mir.span,
                     "Operand path should have handled transmute \
-                    from `Ref` {src:?} to place {dst:?}"
+                    from {src:?} to place {dst:?}"
                 );
             }
             OperandValue::Immediate(..) | OperandValue::Pair(..) => {
@@ -220,17 +223,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 let fake_place = PlaceRef::new_sized_aligned(cast_ptr, cast, align);
                 Some(bx.load_operand(fake_place).val)
             }
+            OperandValue::ZeroSized => {
+                let OperandValueKind::ZeroSized = operand_kind else {
+                    bug!("Found {operand_kind:?} for operand {operand:?}");
+                };
+                if let OperandValueKind::ZeroSized = cast_kind {
+                    Some(OperandValue::ZeroSized)
+                } else {
+                    None
+                }
+            }
             OperandValue::Immediate(imm) => {
                 let OperandValueKind::Immediate(in_scalar) = operand_kind else {
                     bug!("Found {operand_kind:?} for operand {operand:?}");
                 };
-                if let OperandValueKind::Immediate(out_scalar) = cast_kind {
-                    match (in_scalar, out_scalar) {
-                        (ScalarOrZst::Zst, ScalarOrZst::Zst) => {
-                            Some(OperandRef::new_zst(bx, cast).val)
-                        }
-                        (ScalarOrZst::Scalar(in_scalar), ScalarOrZst::Scalar(out_scalar))
-                            if in_scalar.size(self.cx) == out_scalar.size(self.cx) =>
+                if let OperandValueKind::Immediate(out_scalar) = cast_kind
+                    && in_scalar.size(self.cx) == out_scalar.size(self.cx)
                         {
                             let operand_bty = bx.backend_type(operand.layout);
                             let cast_bty = bx.backend_type(cast);
@@ -242,9 +250,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                 out_scalar,
                                 cast_bty,
                             )))
-                        }
-                        _ => None,
-                    }
                 } else {
                     None
                 }
@@ -457,6 +462,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                             OperandValue::Ref(..) => {
                                 bug!("by-ref operand {:?} in `codegen_rvalue_operand`", operand);
                             }
+                            OperandValue::ZeroSized => {
+                                bug!("zero-sized operand {:?} in `codegen_rvalue_operand`", operand);
+                            }
                         };
                         let (lldata, llextra) =
                             base::unsize_ptr(bx, lldata, operand.layout.ty, cast.ty, llextra);
@@ -490,6 +498,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                             OperandValue::Ref(_, _, _) => todo!(),
                             OperandValue::Immediate(v) => (v, None),
                             OperandValue::Pair(v, l) => (v, Some(l)),
+                            OperandValue::ZeroSized => bug!("ZST -- which is not PointerLike -- in DynStar"),
                         };
                         let (lldata, llextra) =
                             base::cast_to_dyn_star(bx, lldata, operand.layout, cast.ty, llextra);
@@ -718,7 +727,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 // According to `rvalue_creates_operand`, only ZST
                 // aggregate rvalues are allowed to be operands.
                 let ty = rvalue.ty(self.mir, self.cx.tcx());
-                OperandRef::new_zst(bx, self.cx.layout_of(self.monomorphize(ty)))
+                OperandRef::zero_sized(self.cx.layout_of(self.monomorphize(ty)))
             }
             mir::Rvalue::ShallowInitBox(ref operand, content_ty) => {
                 let operand = self.codegen_operand(bx, operand);
@@ -936,6 +945,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     // Can always load from a pointer as needed
                     (OperandValueKind::Ref, _) => true,
 
+                    // ZST-to-ZST is the easiest thing ever
+                    (OperandValueKind::ZeroSized, OperandValueKind::ZeroSized) => true,
+
+                    // But if only one of them is a ZST the sizes can't match
+                    (OperandValueKind::ZeroSized, _) | (_, OperandValueKind::ZeroSized) => false,
+
                     // Need to generate an `alloc` to get a pointer from an immediate
                     (OperandValueKind::Immediate(..) | OperandValueKind::Pair(..), OperandValueKind::Ref) => false,
 
@@ -979,12 +994,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
     /// Gets which variant of [`OperandValue`] is expected for a particular type.
     fn value_kind(&self, layout: TyAndLayout<'tcx>) -> OperandValueKind {
-        if self.cx.is_backend_immediate(layout) {
+        if layout.is_zst() {
+            OperandValueKind::ZeroSized
+        } else if self.cx.is_backend_immediate(layout) {
             debug_assert!(!self.cx.is_backend_scalar_pair(layout));
             OperandValueKind::Immediate(match layout.abi {
-                abi::Abi::Scalar(s) => ScalarOrZst::Scalar(s),
-                abi::Abi::Vector { element, .. } => ScalarOrZst::Scalar(element),
-                _ if layout.is_zst() => ScalarOrZst::Zst,
+                abi::Abi::Scalar(s) => s,
+                abi::Abi::Vector { element, .. } => element,
                 x => span_bug!(self.mir.span, "Couldn't translate {x:?} as backend immediate"),
             })
         } else if self.cx.is_backend_scalar_pair(layout) {
@@ -1007,21 +1023,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 #[derive(Debug, Copy, Clone)]
 enum OperandValueKind {
     Ref,
-    Immediate(ScalarOrZst),
+    Immediate(abi::Scalar),
     Pair(abi::Scalar, abi::Scalar),
-}
-
-#[derive(Debug, Copy, Clone)]
-enum ScalarOrZst {
-    Zst,
-    Scalar(abi::Scalar),
-}
-
-impl ScalarOrZst {
-    pub fn size(self, cx: &impl abi::HasDataLayout) -> abi::Size {
-        match self {
-            ScalarOrZst::Zst => abi::Size::ZERO,
-            ScalarOrZst::Scalar(s) => s.size(cx),
-        }
-    }
+    ZeroSized,
 }
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index 7d56cf0aa07..bf660c59cab 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -1,8 +1,142 @@
+const_eval_address_space_full =
+    there are no more free addresses in the address space
+const_eval_align_check_failed = accessing memory with alignment {$has}, but alignment {$required} is required
+const_eval_align_offset_invalid_align =
+    `align_offset` called with non-power-of-two align: {$target_align}
+
+const_eval_alignment_check_failed =
+    accessing memory with alignment {$has}, but alignment {$required} is required
+const_eval_already_reported =
+    an error has already been reported elsewhere (this should not usually be printed)
+const_eval_assume_false =
+    `assume` called with `false`
+
+const_eval_await_non_const =
+    cannot convert `{$ty}` into a future in {const_eval_const_context}s
+const_eval_bounds_check_failed =
+    indexing out of bounds: the len is {$len} but the index is {$index}
+const_eval_box_to_mut = {$front_matter}: encountered a box pointing to mutable memory in a constant
+const_eval_box_to_static = {$front_matter}: encountered a box pointing to a static variable in a constant
+const_eval_box_to_uninhabited = {$front_matter}: encountered a box pointing to uninhabited type {$ty}
+const_eval_call_nonzero_intrinsic =
+    `{$name}` called on 0
+
+const_eval_closure_call =
+    closures need an RFC before allowed to be called in {const_eval_const_context}s
+const_eval_closure_fndef_not_const =
+    function defined here, but it is not `const`
+const_eval_closure_non_const =
+    cannot call non-const closure in {const_eval_const_context}s
+const_eval_consider_dereferencing =
+    consider dereferencing here
+const_eval_const_accesses_static = constant accesses static
+
+const_eval_const_context = {$kind ->
+    [const] constant
+    [static] static
+    [const_fn] constant function
+    *[other] {""}
+}
+
+const_eval_copy_nonoverlapping_overlapping =
+    `copy_nonoverlapping` called on overlapping ranges
+
+const_eval_dangling_box_no_provenance = {$front_matter}: encountered a dangling box ({$pointer} has no provenance)
+const_eval_dangling_box_out_of_bounds = {$front_matter}: encountered a dangling box (going beyond the bounds of its allocation)
+const_eval_dangling_box_use_after_free = {$front_matter}: encountered a dangling box (use-after-free)
+const_eval_dangling_int_pointer =
+    {$bad_pointer_message}: {$pointer} is a dangling pointer (it has no provenance)
+const_eval_dangling_null_pointer =
+    {$bad_pointer_message}: null pointer is a dangling pointer (it has no provenance)
+const_eval_dangling_ptr_in_final = encountered dangling pointer in final constant
+
+const_eval_dangling_ref_no_provenance = {$front_matter}: encountered a dangling reference ({$pointer} has no provenance)
+const_eval_dangling_ref_out_of_bounds = {$front_matter}: encountered a dangling reference (going beyond the bounds of its allocation)
+const_eval_dangling_ref_use_after_free = {$front_matter}: encountered a dangling reference (use-after-free)
+const_eval_dead_local =
+    accessing a dead local variable
+const_eval_dealloc_immutable =
+    deallocating immutable allocation {$alloc}
+
+const_eval_dealloc_incorrect_layout =
+    incorrect layout on deallocation: {$alloc} has size {$size} and alignment {$align}, but gave size {$size_found} and alignment {$align_found}
+
+const_eval_dealloc_kind_mismatch =
+    deallocating {$alloc}, which is {$alloc_kind} memory, using {$kind} deallocation operation
+
+const_eval_deref_coercion_non_const =
+    cannot perform deref coercion on `{$ty}` in {const_eval_const_context}s
+    .note = attempting to deref into `{$target_ty}`
+    .target_note = deref defined here
+const_eval_deref_function_pointer =
+    accessing {$allocation} which contains a function
+const_eval_deref_test = dereferencing pointer failed
+const_eval_deref_vtable_pointer =
+    accessing {$allocation} which contains a vtable
+const_eval_different_allocations =
+    `{$name}` called on pointers into different allocations
+
+const_eval_division_by_zero =
+    dividing by zero
+const_eval_division_overflow =
+    overflow in signed division (dividing MIN by -1)
+const_eval_double_storage_live =
+    StorageLive on a local that was already live
+
+const_eval_dyn_call_not_a_method =
+    `dyn` call trying to call something that is not a method
+
+const_eval_dyn_call_vtable_mismatch =
+    `dyn` call on a pointer whose vtable does not match its type
+
+const_eval_dyn_star_call_vtable_mismatch =
+    `dyn*` call on a pointer whose vtable does not match its type
+
+const_eval_erroneous_constant =
+    erroneous constant used
+
+const_eval_error = {$error_kind ->
+    [static] could not evaluate static initializer
+    [const] evaluation of constant value failed
+    [const_with_path] evaluation of `{$instance}` failed
+    *[other] {""}
+}
+
+const_eval_exact_div_has_remainder =
+    exact_div: {$a} cannot be divided by {$b} without remainder
+
+const_eval_expected_non_ptr = {$front_matter}: encountered `{$value}`, but expected plain (non-pointer) bytes
+const_eval_fn_ptr_call =
+    function pointers need an RFC before allowed to be called in {const_eval_const_context}s
+const_eval_for_loop_into_iter_non_const =
+    cannot convert `{$ty}` into an iterator in {const_eval_const_context}s
+
+const_eval_frame_note = {$times ->
+    [0] {const_eval_frame_note_inner}
+    *[other] [... {$times} additional calls {const_eval_frame_note_inner} ...]
+}
+
+const_eval_frame_note_inner = inside {$where_ ->
+    [closure] closure
+    [instance] `{$instance}`
+    *[other] {""}
+}
+
+const_eval_in_bounds_test = out-of-bounds pointer use
+const_eval_incompatible_calling_conventions =
+    calling a function with calling convention {$callee_conv} using calling convention {$caller_conv}
+
+const_eval_incompatible_return_types =
+    calling a function with return type {$callee_ty} passing return place of type {$caller_ty}
+
+const_eval_incompatible_types =
+    calling a function with argument of type {$callee_ty} passing data of type {$caller_ty}
+
 const_eval_interior_mutability_borrow =
     cannot borrow here, since the borrowed element may contain interior mutability
 
 const_eval_interior_mutable_data_refer =
-    {$kind}s cannot refer to interior mutable data
+    {const_eval_const_context}s cannot refer to interior mutable data
     .label = this borrow of an interior mutable value may end up in the final value
     .help = to fix this, the value can be extracted to a separate `static` item and then referenced
     .teach_note =
@@ -10,19 +144,163 @@ const_eval_interior_mutable_data_refer =
         This would make multiple uses of a constant to be able to see different values and allow circumventing
         the `Send` and `Sync` requirements for shared mutable data, which is unsound.
 
+const_eval_invalid_align =
+    align has to be a power of 2
+
+const_eval_invalid_align_details =
+    invalid align passed to `{$name}`: {$align} is {$err_kind ->
+        [not_power_of_two] not a power of 2
+        [too_large] too large
+        *[other] {""}
+    }
+
+const_eval_invalid_bool =
+    interpreting an invalid 8-bit value as a bool: 0x{$value}
+const_eval_invalid_box_meta = {$front_matter}: encountered invalid box metadata: total size is bigger than largest supported object
+const_eval_invalid_box_slice_meta = {$front_matter}: encountered invalid box metadata: slice is bigger than largest supported object
+const_eval_invalid_char =
+    interpreting an invalid 32-bit value as a char: 0x{$value}
+const_eval_invalid_dealloc =
+    deallocating {$alloc_id}, which is {$kind ->
+        [fn] a function
+        [vtable] a vtable
+        [static_mem] static memory
+        *[other] {""}
+    }
+
+const_eval_invalid_enum_tag = {$front_matter}: encountered {$value}, but expected a valid enum tag
+const_eval_invalid_fn_ptr = {$front_matter}: encountered {$value}, but expected a function pointer
+const_eval_invalid_function_pointer =
+    using {$pointer} as function pointer but it does not point to a function
+const_eval_invalid_meta =
+    invalid metadata in wide pointer: total size is bigger than largest supported object
+const_eval_invalid_meta_slice =
+    invalid metadata in wide pointer: slice is bigger than largest supported object
+const_eval_invalid_ref_meta = {$front_matter}: encountered invalid reference metadata: total size is bigger than largest supported object
+const_eval_invalid_ref_slice_meta = {$front_matter}: encountered invalid reference metadata: slice is bigger than largest supported object
+const_eval_invalid_str =
+    this string is not valid UTF-8: {$err}
+const_eval_invalid_tag =
+    enum value has invalid tag: {$tag}
+const_eval_invalid_transmute =
+    transmuting from {$src_bytes}-byte type to {$dest_bytes}-byte type: `{$src}` -> `{$dest}`
+
+const_eval_invalid_uninit_bytes =
+    reading memory at {$alloc}{$access}, but memory is uninitialized at {$uninit}, and this operation requires initialized memory
+const_eval_invalid_uninit_bytes_unknown =
+    using uninitialized data, but this operation requires initialized memory
+const_eval_invalid_value = constructing invalid value
+const_eval_invalid_value_with_path = constructing invalid value at {$path}
+## The `front_matter`s here refer to either `middle_invalid_value` or `middle_invalid_value_with_path`.
+
+const_eval_invalid_vtable_pointer =
+    using {$pointer} as vtable pointer but it does not point to a vtable
+
+const_eval_invalid_vtable_ptr = {$front_matter}: encountered {$value}, but expected a vtable pointer
+
+const_eval_live_drop =
+    destructor of `{$dropped_ty}` cannot be evaluated at compile-time
+    .label = the destructor for this type cannot be evaluated in {const_eval_const_context}s
+    .dropped_at_label = value is dropped here
+
+const_eval_long_running =
+    constant evaluation is taking a long time
+    .note = this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval.
+        If your compilation actually takes a long time, you can safely allow the lint.
+    .label = the const evaluator is currently interpreting this expression
+    .help = the constant being evaluated
+
 const_eval_max_num_nodes_in_const = maximum number of nodes exceeded in constant {$global_const_id}
 
+const_eval_memory_access_test = memory access failed
+const_eval_memory_exhausted =
+    tried to allocate more memory than available to compiler
+const_eval_modified_global =
+    modifying a static's initial value from another static's initializer
+
 const_eval_mut_deref =
-    mutation through a reference is not allowed in {$kind}s
+    mutation through a reference is not allowed in {const_eval_const_context}s
 
+const_eval_mutable_ref_in_const = {$front_matter}: encountered mutable reference in a `const`
+const_eval_never_val = {$front_matter}: encountered a value of the never type `!`
 const_eval_non_const_fmt_macro_call =
-    cannot call non-const formatting macro in {$kind}s
+    cannot call non-const formatting macro in {const_eval_const_context}s
 
 const_eval_non_const_fn_call =
-    cannot call non-const fn `{$def_path_str}` in {$kind}s
+    cannot call non-const fn `{$def_path_str}` in {const_eval_const_context}s
+
+const_eval_non_const_impl =
+    impl defined here, but it is not `const`
+
+const_eval_noreturn_asm_returned =
+    returned from noreturn inline assembly
+
+const_eval_not_enough_caller_args =
+    calling a function with fewer arguments than it requires
+
+const_eval_null_box = {$front_matter}: encountered a null box
+const_eval_null_fn_ptr = {$front_matter}: encountered a null function pointer
+const_eval_null_ref = {$front_matter}: encountered a null reference
+const_eval_nullable_ptr_out_of_range = {$front_matter}: encountered a potentially null pointer, but expected something that cannot possibly fail to be {$in_range}
+const_eval_nullary_intrinsic_fail =
+    could not evaluate nullary intrinsic
+
+const_eval_offset_from_overflow =
+    `{$name}` called when first pointer is too far ahead of second
+
+const_eval_offset_from_test = out-of-bounds `offset_from`
+const_eval_offset_from_underflow =
+    `{$name}` called when first pointer is too far before second
+
+const_eval_operator_non_const =
+    cannot call non-const operator in {const_eval_const_context}s
+const_eval_out_of_range = {$front_matter}: encountered {$value}, but expected something {$in_range}
+const_eval_overflow =
+    overflow executing `{$name}`
+
+const_eval_overflow_shift =
+    overflowing shift by {$val} in `{$name}`
+
+const_eval_panic =
+    the evaluated program panicked at '{$msg}', {$file}:{$line}:{$col}
 
 const_eval_panic_non_str = argument to `panic!()` in a const context must have type `&str`
 
+const_eval_partial_pointer_copy =
+    unable to copy parts of a pointer from memory at {$ptr}
+const_eval_partial_pointer_overwrite =
+    unable to overwrite parts of a pointer in memory at {$ptr}
+const_eval_pointer_arithmetic_overflow =
+    overflowing in-bounds pointer arithmetic
+const_eval_pointer_arithmetic_test = out-of-bounds pointer arithmetic
+const_eval_pointer_out_of_bounds =
+    {$bad_pointer_message}: {$alloc_id} has size {$alloc_size}, so pointer to {$ptr_size} {$ptr_size ->
+        [1] byte
+        *[many] bytes
+    } starting at offset {$ptr_offset} is out-of-bounds
+const_eval_pointer_use_after_free =
+    pointer to {$allocation} was dereferenced after this allocation got freed
+const_eval_ptr_as_bytes_1 =
+    this code performed an operation that depends on the underlying bytes representing a pointer
+const_eval_ptr_as_bytes_2 =
+    the absolute address of a pointer is not known at compile-time, so such operations are not supported
+const_eval_ptr_out_of_range = {$front_matter}: encountered a pointer, but expected something that cannot possibly fail to be {$in_range}
+const_eval_question_branch_non_const =
+    `?` cannot determine the branch of `{$ty}` in {const_eval_const_context}s
+
+const_eval_question_from_residual_non_const =
+    `?` cannot convert from residual of `{$ty}` in {const_eval_const_context}s
+
+const_eval_range = in the range {$lo}..={$hi}
+const_eval_range_lower = greater or equal to {$lo}
+const_eval_range_singular = equal to {$lo}
+const_eval_range_upper = less or equal to {$hi}
+const_eval_range_wrapping = less or equal to {$hi}, or greater or equal to {$lo}
+const_eval_raw_bytes = the raw bytes of the constant (size: {$size}, align: {$align}) {"{"}{$bytes}{"}"}
+
+const_eval_raw_eq_with_provenance =
+    `raw_eq` on bytes with provenance
+
 const_eval_raw_ptr_comparison =
     pointers cannot be reliably compared during const eval
     .note = see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
@@ -32,8 +310,36 @@ const_eval_raw_ptr_to_int =
     .note = at compile-time, pointers do not have an integer value
     .note2 = avoiding this restriction via `transmute`, `union`, or raw pointers leads to compile-time undefined behavior
 
+const_eval_read_extern_static =
+    cannot read from extern static ({$did})
+const_eval_read_pointer_as_bytes =
+    unable to turn pointer into raw bytes
+const_eval_realloc_or_alloc_with_offset =
+    {$kind ->
+        [dealloc] deallocating
+        [realloc] reallocating
+        *[other] {""}
+    } {$ptr} which does not point to the beginning of an object
+
+const_eval_ref_to_mut = {$front_matter}: encountered a reference pointing to mutable memory in a constant
+const_eval_ref_to_static = {$front_matter}: encountered a reference pointing to a static variable in a constant
+const_eval_ref_to_uninhabited = {$front_matter}: encountered a reference pointing to uninhabited type {$ty}
+const_eval_remainder_by_zero =
+    calculating the remainder with a divisor of zero
+const_eval_remainder_overflow =
+    overflow in signed remainder (dividing MIN by -1)
+const_eval_scalar_size_mismatch =
+    scalar size mismatch: expected {$target_size} bytes but got {$data_size} bytes instead
+const_eval_size_of_unsized =
+    size_of called on unsized type `{$ty}`
+const_eval_size_overflow =
+    overflow computing total size of `{$name}`
+
+const_eval_stack_frame_limit_reached =
+    reached the configured maximum number of stack frames
+
 const_eval_static_access =
-    {$kind}s cannot refer to statics
+    {const_eval_const_context}s cannot refer to statics
     .help = consider extracting the value of the `static` to a `const`, and referring to that
     .teach_note = `static` and `const` variables can refer to other `const` variables. A `const` variable, however, cannot refer to a `static` variable.
     .teach_help = To fix this, the value can be extracted to a `const` and then used.
@@ -41,27 +347,34 @@ const_eval_static_access =
 const_eval_thread_local_access =
     thread-local statics cannot be accessed at compile-time
 
-const_eval_transient_mut_borrow = mutable references are not allowed in {$kind}s
+const_eval_thread_local_static =
+    cannot access thread local static ({$did})
+const_eval_too_generic =
+    encountered overly generic constant
+const_eval_too_many_caller_args =
+    calling a function with more arguments than it expected
 
-const_eval_transient_mut_borrow_raw = raw mutable references are not allowed in {$kind}s
+const_eval_transient_mut_borrow = mutable references are not allowed in {const_eval_const_context}s
 
-const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in {$kind}s
+const_eval_transient_mut_borrow_raw = raw mutable references are not allowed in {const_eval_const_context}s
+
+const_eval_try_block_from_output_non_const =
+    `try` block cannot convert `{$ty}` to the result in {const_eval_const_context}s
+const_eval_unaligned_box = {$front_matter}: encountered an unaligned box (required {$required_bytes} byte alignment but found {$found_bytes})
+const_eval_unaligned_ref = {$front_matter}: encountered an unaligned reference (required {$required_bytes} byte alignment but found {$found_bytes})
+const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in {const_eval_const_context}s
 
 const_eval_unallowed_heap_allocations =
-    allocations are not allowed in {$kind}s
-    .label = allocation not allowed in {$kind}s
+    allocations are not allowed in {const_eval_const_context}s
+    .label = allocation not allowed in {const_eval_const_context}s
     .teach_note =
         The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time.
 
 const_eval_unallowed_inline_asm =
-    inline assembly is not allowed in {$kind}s
-
+    inline assembly is not allowed in {const_eval_const_context}s
 const_eval_unallowed_mutable_refs =
-    mutable references are not allowed in the final value of {$kind}s
+    mutable references are not allowed in the final value of {const_eval_const_context}s
     .teach_note =
-        References in statics and constants may only refer to immutable values.
-
-
         Statics are shared everywhere, and if they refer to mutable data one might violate memory
         safety since holding multiple mutable references to shared data is not allowed.
 
@@ -69,7 +382,7 @@ const_eval_unallowed_mutable_refs =
         If you really want global mutable state, try using static mut or a global UnsafeCell.
 
 const_eval_unallowed_mutable_refs_raw =
-    raw mutable references are not allowed in the final value of {$kind}s
+    raw mutable references are not allowed in the final value of {const_eval_const_context}s
     .teach_note =
         References in statics and constants may only refer to immutable values.
 
@@ -83,9 +396,59 @@ const_eval_unallowed_mutable_refs_raw =
 const_eval_unallowed_op_in_const_context =
     {$msg}
 
+const_eval_undefined_behavior =
+    it is undefined behavior to use this value
+
+const_eval_undefined_behavior_note =
+    The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
+
+const_eval_uninhabited_enum_variant_written =
+    writing discriminant of an uninhabited enum
+const_eval_uninhabited_val = {$front_matter}: encountered a value of uninhabited type `{$ty}`
+const_eval_uninit = {$front_matter}: encountered uninitialized bytes
+const_eval_uninit_bool = {$front_matter}: encountered uninitialized memory, but expected a boolean
+const_eval_uninit_box = {$front_matter}: encountered uninitialized memory, but expected a box
+const_eval_uninit_char = {$front_matter}: encountered uninitialized memory, but expected a unicode scalar value
+const_eval_uninit_enum_tag = {$front_matter}: encountered uninitialized bytes, but expected a valid enum tag
+const_eval_uninit_float = {$front_matter}: encountered uninitialized memory, but expected a floating point number
+const_eval_uninit_fn_ptr = {$front_matter}: encountered uninitialized memory, but expected a function pointer
+const_eval_uninit_init_scalar = {$front_matter}: encountered uninitialized memory, but expected initialized scalar value
+const_eval_uninit_int = {$front_matter}: encountered uninitialized memory, but expected an integer
+const_eval_uninit_raw_ptr = {$front_matter}: encountered uninitialized memory, but expected a raw pointer
+const_eval_uninit_ref = {$front_matter}: encountered uninitialized memory, but expected a reference
+const_eval_uninit_str = {$front_matter}: encountered uninitialized data in `str`
+const_eval_uninit_unsized_local =
+    unsized local is used while uninitialized
+const_eval_unreachable = entering unreachable code
+const_eval_unreachable_unwind =
+    unwinding past a stack frame that does not allow unwinding
+
+const_eval_unsafe_cell = {$front_matter}: encountered `UnsafeCell` in a `const`
+const_eval_unsigned_offset_from_overflow =
+    `ptr_offset_from_unsigned` called when first pointer has smaller offset than second: {$a_offset} < {$b_offset}
+
 const_eval_unstable_const_fn = `{$def_path}` is not yet stable as a const fn
 
 const_eval_unstable_in_stable =
     const-stable function cannot use `#[feature({$gate})]`
     .unstable_sugg = if it is not part of the public API, make this function unstably const
     .bypass_sugg = otherwise `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks
+
+const_eval_unsupported_untyped_pointer = unsupported untyped pointer in constant
+    .note = memory only reachable via raw pointers is not supported
+
+const_eval_unterminated_c_string =
+    reading a null-terminated string starting at {$pointer} with no null found before end of allocation
+
+const_eval_unwind_past_top =
+    unwinding past the topmost frame of the stack
+
+const_eval_upcast_mismatch =
+    upcast on a pointer whose vtable does not match its type
+
+const_eval_validation_invalid_bool = {$front_matter}: encountered {$value}, but expected a boolean
+const_eval_validation_invalid_char = {$front_matter}: encountered {$value}, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
+const_eval_write_to_read_only =
+    writing to {$allocation} which is read-only
+const_eval_zst_pointer_out_of_bounds =
+    {$bad_pointer_message}: {$alloc_id} has size {$alloc_size}, so pointer at offset {$ptr_offset} is out-of-bounds
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index c591ff75ab8..7890d878d08 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -1,17 +1,15 @@
-use std::error::Error;
-use std::fmt;
+use std::mem;
 
-use rustc_errors::Diagnostic;
+use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, IntoDiagnostic, IntoDiagnosticArg};
 use rustc_middle::mir::AssertKind;
-use rustc_middle::query::TyCtxtAt;
+use rustc_middle::ty::TyCtxt;
 use rustc_middle::ty::{layout::LayoutError, ConstInt};
-use rustc_span::{Span, Symbol};
+use rustc_span::source_map::Spanned;
+use rustc_span::{ErrorGuaranteed, Span, Symbol};
 
 use super::InterpCx;
-use crate::interpret::{
-    struct_error, ErrorHandled, FrameInfo, InterpError, InterpErrorInfo, Machine, MachineStopType,
-    UnsupportedOpInfo,
-};
+use crate::errors::{self, FrameNote, ReportErrorExt};
+use crate::interpret::{ErrorHandled, InterpError, InterpErrorInfo, Machine, MachineStopType};
 
 /// The CTFE machine has some custom error kinds.
 #[derive(Clone, Debug)]
@@ -23,7 +21,35 @@ pub enum ConstEvalErrKind {
     Abort(String),
 }
 
-impl MachineStopType for ConstEvalErrKind {}
+impl MachineStopType for ConstEvalErrKind {
+    fn diagnostic_message(&self) -> DiagnosticMessage {
+        use crate::fluent_generated::*;
+        use ConstEvalErrKind::*;
+        match self {
+            ConstAccessesStatic => const_eval_const_accesses_static,
+            ModifiedGlobal => const_eval_modified_global,
+            Panic { .. } => const_eval_panic,
+            AssertFailure(x) => x.diagnostic_message(),
+            Abort(msg) => msg.to_string().into(),
+        }
+    }
+    fn add_args(
+        self: Box<Self>,
+        adder: &mut dyn FnMut(std::borrow::Cow<'static, str>, DiagnosticArgValue<'static>),
+    ) {
+        use ConstEvalErrKind::*;
+        match *self {
+            ConstAccessesStatic | ModifiedGlobal | Abort(_) => {}
+            AssertFailure(kind) => kind.add_args(adder),
+            Panic { msg, line, col, file } => {
+                adder("msg".into(), msg.into_diagnostic_arg());
+                adder("file".into(), file.into_diagnostic_arg());
+                adder("line".into(), line.into_diagnostic_arg());
+                adder("col".into(), col.into_diagnostic_arg());
+            }
+        }
+    }
+}
 
 // The errors become `MachineStop` with plain strings when being raised.
 // `ConstEvalErr` (in `librustc_middle/mir/interpret/error.rs`) knows to
@@ -34,151 +60,117 @@ impl<'tcx> Into<InterpErrorInfo<'tcx>> for ConstEvalErrKind {
     }
 }
 
-impl fmt::Display for ConstEvalErrKind {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use self::ConstEvalErrKind::*;
-        match self {
-            ConstAccessesStatic => write!(f, "constant accesses static"),
-            ModifiedGlobal => {
-                write!(f, "modifying a static's initial value from another static's initializer")
-            }
-            AssertFailure(msg) => write!(f, "{:?}", msg),
-            Panic { msg, line, col, file } => {
-                write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col)
-            }
-            Abort(msg) => write!(f, "{}", msg),
-        }
-    }
-}
-
-impl Error for ConstEvalErrKind {}
+pub fn get_span_and_frames<'tcx, 'mir, M: Machine<'mir, 'tcx>>(
+    ecx: &InterpCx<'mir, 'tcx, M>,
+) -> (Span, Vec<errors::FrameNote>)
+where
+    'tcx: 'mir,
+{
+    let mut stacktrace = ecx.generate_stacktrace();
+    // Filter out `requires_caller_location` frames.
+    stacktrace.retain(|frame| !frame.instance.def.requires_caller_location(*ecx.tcx));
+    let span = stacktrace.first().map(|f| f.span).unwrap_or(ecx.tcx.span);
 
-/// When const-evaluation errors, this type is constructed with the resulting information,
-/// and then used to emit the error as a lint or hard error.
-#[derive(Debug)]
-pub(super) struct ConstEvalErr<'tcx> {
-    pub span: Span,
-    pub error: InterpError<'tcx>,
-    pub stacktrace: Vec<FrameInfo<'tcx>>,
-}
+    let mut frames = Vec::new();
 
-impl<'tcx> ConstEvalErr<'tcx> {
-    /// Turn an interpreter error into something to report to the user.
-    /// As a side-effect, if RUSTC_CTFE_BACKTRACE is set, this prints the backtrace.
-    /// Should be called only if the error is actually going to be reported!
-    pub fn new<'mir, M: Machine<'mir, 'tcx>>(
-        ecx: &InterpCx<'mir, 'tcx, M>,
-        error: InterpErrorInfo<'tcx>,
-        span: Option<Span>,
-    ) -> ConstEvalErr<'tcx>
-    where
-        'tcx: 'mir,
-    {
-        error.print_backtrace();
-        let mut stacktrace = ecx.generate_stacktrace();
-        // Filter out `requires_caller_location` frames.
-        stacktrace.retain(|frame| !frame.instance.def.requires_caller_location(*ecx.tcx));
-        // If `span` is missing, use topmost remaining frame, or else the "root" span from `ecx.tcx`.
-        let span = span.or_else(|| stacktrace.first().map(|f| f.span)).unwrap_or(ecx.tcx.span);
-        ConstEvalErr { error: error.into_kind(), stacktrace, span }
-    }
-
-    pub(super) fn report(&self, tcx: TyCtxtAt<'tcx>, message: &str) -> ErrorHandled {
-        self.report_decorated(tcx, message, |_| {})
-    }
-
-    #[instrument(level = "trace", skip(self, decorate))]
-    pub(super) fn decorate(&self, err: &mut Diagnostic, decorate: impl FnOnce(&mut Diagnostic)) {
-        trace!("reporting const eval failure at {:?}", self.span);
-        // Add some more context for select error types.
-        match self.error {
-            InterpError::Unsupported(
-                UnsupportedOpInfo::ReadPointerAsBytes
-                | UnsupportedOpInfo::PartialPointerOverwrite(_)
-                | UnsupportedOpInfo::PartialPointerCopy(_),
-            ) => {
-                err.help("this code performed an operation that depends on the underlying bytes representing a pointer");
-                err.help("the absolute address of a pointer is not known at compile-time, so such operations are not supported");
+    // Add notes to the backtrace. Don't print a single-line backtrace though.
+    if stacktrace.len() > 1 {
+        // Helper closure to print duplicated lines.
+        let mut add_frame = |mut frame: errors::FrameNote| {
+            frames.push(errors::FrameNote { times: 0, ..frame.clone() });
+            // Don't print [... additional calls ...] if the number of lines is small
+            if frame.times < 3 {
+                let times = frame.times;
+                frame.times = 0;
+                frames.extend(std::iter::repeat(frame).take(times as usize));
+            } else {
+                frames.push(frame);
             }
-            _ => {}
-        }
-        // Add spans for the stacktrace. Don't print a single-line backtrace though.
-        if self.stacktrace.len() > 1 {
-            // Helper closure to print duplicated lines.
-            let mut flush_last_line = |last_frame: Option<(String, _)>, times| {
-                if let Some((line, span)) = last_frame {
-                    err.span_note(span, line.clone());
-                    // Don't print [... additional calls ...] if the number of lines is small
-                    if times < 3 {
-                        for _ in 0..times {
-                            err.span_note(span, line.clone());
-                        }
-                    } else {
-                        err.span_note(
-                            span,
-                            format!("[... {} additional calls {} ...]", times, &line),
-                        );
-                    }
-                }
-            };
+        };
 
-            let mut last_frame = None;
-            let mut times = 0;
-            for frame_info in &self.stacktrace {
-                let frame = (frame_info.to_string(), frame_info.span);
-                if last_frame.as_ref() == Some(&frame) {
-                    times += 1;
-                } else {
-                    flush_last_line(last_frame, times);
+        let mut last_frame: Option<errors::FrameNote> = None;
+        for frame_info in &stacktrace {
+            let frame = frame_info.as_note(*ecx.tcx);
+            match last_frame.as_mut() {
+                Some(last_frame)
+                    if last_frame.span == frame.span
+                        && last_frame.where_ == frame.where_
+                        && last_frame.instance == frame.instance =>
+                {
+                    last_frame.times += 1;
+                }
+                Some(last_frame) => {
+                    add_frame(mem::replace(last_frame, frame));
+                }
+                None => {
                     last_frame = Some(frame);
-                    times = 0;
                 }
             }
-            flush_last_line(last_frame, times);
         }
-        // Let the caller attach any additional information it wants.
-        decorate(err);
+        if let Some(frame) = last_frame {
+            add_frame(frame);
+        }
     }
 
-    /// Create a diagnostic for this const eval error.
-    ///
-    /// Sets the message passed in via `message` and adds span labels with detailed error
-    /// information before handing control back to `decorate` to do any final annotations,
-    /// after which the diagnostic is emitted.
-    ///
-    /// If `lint_root.is_some()` report it as a lint, else report it as a hard error.
-    /// (Except that for some errors, we ignore all that -- see `must_error` below.)
-    #[instrument(skip(self, tcx, decorate), level = "debug")]
-    pub(super) fn report_decorated(
-        &self,
-        tcx: TyCtxtAt<'tcx>,
-        message: &str,
-        decorate: impl FnOnce(&mut Diagnostic),
-    ) -> ErrorHandled {
-        debug!("self.error: {:?}", self.error);
-        // Special handling for certain errors
-        match &self.error {
-            // Don't emit a new diagnostic for these errors
-            err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
-                ErrorHandled::TooGeneric
-            }
-            err_inval!(AlreadyReported(error_reported)) => ErrorHandled::Reported(*error_reported),
-            err_inval!(Layout(LayoutError::SizeOverflow(_))) => {
-                // We must *always* hard error on these, even if the caller wants just a lint.
-                // The `message` makes little sense here, this is a more serious error than the
-                // caller thinks anyway.
-                // See <https://github.com/rust-lang/rust/pull/63152>.
-                let mut err = struct_error(tcx, &self.error.to_string());
-                self.decorate(&mut err, decorate);
-                ErrorHandled::Reported(err.emit().into())
-            }
-            _ => {
-                // Report as hard error.
-                let mut err = struct_error(tcx, message);
-                err.span_label(self.span, self.error.to_string());
-                self.decorate(&mut err, decorate);
-                ErrorHandled::Reported(err.emit().into())
+    (span, frames)
+}
+
+/// Create a diagnostic for a const eval error.
+///
+/// This will use the `mk` function for creating the error which will get passed labels according to
+/// the `InterpError` and the span and a stacktrace of current execution according to
+/// `get_span_and_frames`.
+pub(super) fn report<'tcx, C, F, E>(
+    tcx: TyCtxt<'tcx>,
+    error: InterpError<'tcx>,
+    span: Option<Span>,
+    get_span_and_frames: C,
+    mk: F,
+) -> ErrorHandled
+where
+    C: FnOnce() -> (Span, Vec<FrameNote>),
+    F: FnOnce(Span, Vec<FrameNote>) -> E,
+    E: IntoDiagnostic<'tcx, ErrorGuaranteed>,
+{
+    // Special handling for certain errors
+    match error {
+        // Don't emit a new diagnostic for these errors
+        err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
+            ErrorHandled::TooGeneric
+        }
+        err_inval!(AlreadyReported(error_reported)) => ErrorHandled::Reported(error_reported),
+        err_inval!(Layout(layout_error @ LayoutError::SizeOverflow(_))) => {
+            // We must *always* hard error on these, even if the caller wants just a lint.
+            // The `message` makes little sense here, this is a more serious error than the
+            // caller thinks anyway.
+            // See <https://github.com/rust-lang/rust/pull/63152>.
+            let (our_span, frames) = get_span_and_frames();
+            let span = span.unwrap_or(our_span);
+            let mut err =
+                tcx.sess.create_err(Spanned { span, node: layout_error.into_diagnostic() });
+            err.code(rustc_errors::error_code!(E0080));
+            let Some((mut err, handler)) = err.into_diagnostic() else {
+                    panic!("did not emit diag");
+                };
+            for frame in frames {
+                err.eager_subdiagnostic(handler, frame);
             }
+
+            ErrorHandled::Reported(handler.emit_diagnostic(&mut err).unwrap().into())
+        }
+        _ => {
+            // Report as hard error.
+            let (our_span, frames) = get_span_and_frames();
+            let span = span.unwrap_or(our_span);
+            let err = mk(span, frames);
+            let mut err = tcx.sess.create_err(err);
+
+            let msg = error.diagnostic_message();
+            error.add_args(&tcx.sess.parse_sess.span_diagnostic, &mut err);
+
+            // Use *our* span to label the interp error
+            err.span_label(our_span, msg);
+            ErrorHandled::Reported(err.emit().into())
         }
     }
 }
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index 046d2052968..8b8e8ff58e9 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -1,12 +1,12 @@
 use crate::const_eval::CheckAlignment;
-use std::borrow::Cow;
+use crate::errors::ConstEvalError;
 
 use either::{Left, Right};
 
 use rustc_hir::def::DefKind;
 use rustc_middle::mir;
-use rustc_middle::mir::interpret::ErrorHandled;
-use rustc_middle::mir::pretty::display_allocation;
+use rustc_middle::mir::interpret::{ErrorHandled, InterpErrorInfo};
+use rustc_middle::mir::pretty::write_allocation_bytes;
 use rustc_middle::traits::Reveal;
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::print::with_no_trimmed_paths;
@@ -14,7 +14,8 @@ use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::source_map::Span;
 use rustc_target::abi::{self, Abi};
 
-use super::{CompileTimeEvalContext, CompileTimeInterpreter, ConstEvalErr};
+use super::{CompileTimeEvalContext, CompileTimeInterpreter};
+use crate::errors;
 use crate::interpret::eval_nullary_intrinsic;
 use crate::interpret::{
     intern_const_alloc_recursive, Allocation, ConstAlloc, ConstValue, CtfeValidationMode, GlobalId,
@@ -22,10 +23,6 @@ use crate::interpret::{
     RefTracking, StackPopCleanup,
 };
 
-const NOTE_ON_UNDEFINED_BEHAVIOR_ERROR: &str = "The rules on what exactly is undefined behavior aren't clear, \
-     so this check might be overzealous. Please open an issue on the rustc \
-     repository if you believe it should not be considered undefined behavior.";
-
 // Returns a pointer to where the result lives
 fn eval_body_using_ecx<'mir, 'tcx>(
     ecx: &mut CompileTimeEvalContext<'mir, 'tcx>,
@@ -103,7 +100,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>(
         tcx,
         root_span,
         param_env,
-        CompileTimeInterpreter::new(tcx.const_eval_limit(), can_access_statics, CheckAlignment::No),
+        CompileTimeInterpreter::new(can_access_statics, CheckAlignment::No),
     )
 }
 
@@ -253,8 +250,14 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
         };
         return eval_nullary_intrinsic(tcx, key.param_env, def_id, substs).map_err(|error| {
             let span = tcx.def_span(def_id);
-            let error = ConstEvalErr { error: error.into_kind(), stacktrace: vec![], span };
-            error.report(tcx.at(span), "could not evaluate nullary intrinsic")
+
+            super::report(
+                tcx,
+                error.into_kind(),
+                Some(span),
+                || (span, vec![]),
+                |span, _| errors::NullaryIntrinsicError { span },
+            )
         });
     }
 
@@ -306,7 +309,6 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
         // Statics (and promoteds inside statics) may access other statics, because unlike consts
         // they do not have to behave "as if" they were evaluated at runtime.
         CompileTimeInterpreter::new(
-            tcx.const_eval_limit(),
             /*can_access_statics:*/ is_static,
             if tcx.sess.opts.unstable_opts.extra_const_ub_checks {
                 CheckAlignment::Error
@@ -319,9 +321,11 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
     let res = ecx.load_mir(cid.instance.def, cid.promoted);
     match res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, &body)) {
         Err(error) => {
-            let err = ConstEvalErr::new(&ecx, error, None);
-            let msg = if is_static {
-                Cow::from("could not evaluate static initializer")
+            let (error, backtrace) = error.into_parts();
+            backtrace.print_backtrace();
+
+            let (kind, instance) = if is_static {
+                ("static", String::new())
             } else {
                 // If the current item has generics, we'd like to enrich the message with the
                 // instance and its substs: to show the actual compile-time values, in addition to
@@ -329,19 +333,29 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
                 let instance = &key.value.instance;
                 if !instance.substs.is_empty() {
                     let instance = with_no_trimmed_paths!(instance.to_string());
-                    let msg = format!("evaluation of `{}` failed", instance);
-                    Cow::from(msg)
+                    ("const_with_path", instance)
                 } else {
-                    Cow::from("evaluation of constant value failed")
+                    ("const", String::new())
                 }
             };
 
-            Err(err.report(ecx.tcx.at(err.span), &msg))
+            Err(super::report(
+                *ecx.tcx,
+                error,
+                None,
+                || super::get_span_and_frames(&ecx),
+                |span, frames| ConstEvalError {
+                    span,
+                    error_kind: kind,
+                    instance,
+                    frame_notes: frames,
+                },
+            ))
         }
         Ok(mplace) => {
             // Since evaluation had no errors, validate the resulting constant.
             // This is a separate `try` block to provide more targeted error reporting.
-            let validation = try {
+            let validation: Result<_, InterpErrorInfo<'_>> = try {
                 let mut ref_tracking = RefTracking::new(mplace);
                 let mut inner = false;
                 while let Some((mplace, path)) = ref_tracking.todo.pop() {
@@ -358,23 +372,37 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
                 }
             };
             let alloc_id = mplace.ptr.provenance.unwrap();
+
+            // Validation failed, report an error. This is always a hard error.
             if let Err(error) = validation {
-                // Validation failed, report an error. This is always a hard error.
-                let err = ConstEvalErr::new(&ecx, error, None);
-                Err(err.report_decorated(
-                    ecx.tcx,
-                    "it is undefined behavior to use this value",
-                    |diag| {
-                        if matches!(err.error, InterpError::UndefinedBehavior(_)) {
-                            diag.note(NOTE_ON_UNDEFINED_BEHAVIOR_ERROR);
-                        }
-                        diag.note(format!(
-                            "the raw bytes of the constant ({}",
-                            display_allocation(
-                                *ecx.tcx,
-                                ecx.tcx.global_alloc(alloc_id).unwrap_memory().inner()
-                            )
-                        ));
+                let (error, backtrace) = error.into_parts();
+                backtrace.print_backtrace();
+
+                let ub_note = matches!(error, InterpError::UndefinedBehavior(_)).then(|| {});
+
+                let alloc = ecx.tcx.global_alloc(alloc_id).unwrap_memory().inner();
+                let mut bytes = String::new();
+                if alloc.size() != abi::Size::ZERO {
+                    bytes = "\n".into();
+                    // FIXME(translation) there might be pieces that are translatable.
+                    write_allocation_bytes(*ecx.tcx, alloc, &mut bytes, "    ").unwrap();
+                }
+                let raw_bytes = errors::RawBytesNote {
+                    size: alloc.size().bytes(),
+                    align: alloc.align.bytes(),
+                    bytes,
+                };
+
+                Err(super::report(
+                    *ecx.tcx,
+                    error,
+                    None,
+                    || super::get_span_and_frames(&ecx),
+                    move |span, frames| errors::UndefinedBehavior {
+                        span,
+                        ub_note,
+                        frames,
+                        raw_bytes,
                     },
                 ))
             } else {
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 58b5755af07..7391f567040 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -16,25 +16,37 @@ use std::fmt;
 use rustc_ast::Mutability;
 use rustc_hir::def_id::DefId;
 use rustc_middle::mir::AssertMessage;
-use rustc_session::Limit;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_target::abi::{Align, Size};
 use rustc_target::spec::abi::Abi as CallAbi;
 
+use crate::errors::{LongRunning, LongRunningWarn};
 use crate::interpret::{
     self, compile_time_machine, AllocId, ConstAllocation, FnVal, Frame, ImmTy, InterpCx,
     InterpResult, OpTy, PlaceTy, Pointer, Scalar,
 };
+use crate::{errors, fluent_generated as fluent};
 
 use super::error::*;
 
+/// When hitting this many interpreted terminators we emit a deny by default lint
+/// that notfies the user that their constant takes a long time to evaluate. If that's
+/// what they intended, they can just allow the lint.
+const LINT_TERMINATOR_LIMIT: usize = 2_000_000;
+/// The limit used by `-Z tiny-const-eval-limit`. This smaller limit is useful for internal
+/// tests not needing to run 30s or more to show some behaviour.
+const TINY_LINT_TERMINATOR_LIMIT: usize = 20;
+/// After this many interpreted terminators, we start emitting progress indicators at every
+/// power of two of interpreted terminators.
+const PROGRESS_INDICATOR_START: usize = 4_000_000;
+
 /// Extra machine state for CTFE, and the Machine instance
 pub struct CompileTimeInterpreter<'mir, 'tcx> {
-    /// For now, the number of terminators that can be evaluated before we throw a resource
-    /// exhaustion error.
+    /// The number of terminators that have been evaluated.
     ///
-    /// Setting this to `0` disables the limit and allows the interpreter to run forever.
-    pub(super) steps_remaining: usize,
+    /// This is used to produce lints informing the user that the compiler is not stuck.
+    /// Set to `usize::MAX` to never report anything.
+    pub(super) num_evaluated_steps: usize,
 
     /// The virtual call stack.
     pub(super) stack: Vec<Frame<'mir, 'tcx, AllocId, ()>>,
@@ -72,13 +84,9 @@ impl CheckAlignment {
 }
 
 impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
-    pub(crate) fn new(
-        const_eval_limit: Limit,
-        can_access_statics: bool,
-        check_alignment: CheckAlignment,
-    ) -> Self {
+    pub(crate) fn new(can_access_statics: bool, check_alignment: CheckAlignment) -> Self {
         CompileTimeInterpreter {
-            steps_remaining: const_eval_limit.0,
+            num_evaluated_steps: 0,
             stack: Vec::new(),
             can_access_statics,
             check_alignment,
@@ -247,7 +255,10 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
         let target_align = self.read_scalar(&args[1])?.to_target_usize(self)?;
 
         if !target_align.is_power_of_two() {
-            throw_ub_format!("`align_offset` called with non-power-of-two align: {}", target_align);
+            throw_ub_custom!(
+                fluent::const_eval_align_offset_invalid_align,
+                target_align = target_align,
+            );
         }
 
         match self.ptr_try_get_alloc_id(ptr) {
@@ -353,15 +364,18 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
                 "`alignment_check_failed` called when no alignment check requested"
             ),
             CheckAlignment::FutureIncompat => {
-                let err = ConstEvalErr::new(ecx, err, None);
-                ecx.tcx.struct_span_lint_hir(
+                let (_, backtrace) = err.into_parts();
+                backtrace.print_backtrace();
+                let (span, frames) = super::get_span_and_frames(&ecx);
+
+                ecx.tcx.emit_spanned_lint(
                     INVALID_ALIGNMENT,
                     ecx.stack().iter().find_map(|frame| frame.lint_root()).unwrap_or(CRATE_HIR_ID),
-                    err.span,
-                    err.error.to_string(),
-                    |db| {
-                        err.decorate(db, |_| {});
-                        db
+                    span,
+                    errors::AlignmentCheckFailed {
+                        has: has.bytes(),
+                        required: required.bytes(),
+                        frames,
                     },
                 );
                 Ok(())
@@ -475,7 +489,12 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
 
                 let align = match Align::from_bytes(align) {
                     Ok(a) => a,
-                    Err(err) => throw_ub_format!("align has to be a power of 2, {}", err),
+                    Err(err) => throw_ub_custom!(
+                        fluent::const_eval_invalid_align_details,
+                        name = "const_allocate",
+                        err_kind = err.diag_ident(),
+                        align = err.align()
+                    ),
                 };
 
                 let ptr = ecx.allocate_ptr(
@@ -493,7 +512,12 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
                 let size = Size::from_bytes(size);
                 let align = match Align::from_bytes(align) {
                     Ok(a) => a,
-                    Err(err) => throw_ub_format!("align has to be a power of 2, {}", err),
+                    Err(err) => throw_ub_custom!(
+                        fluent::const_eval_invalid_align_details,
+                        name = "const_deallocate",
+                        err_kind = err.diag_ident(),
+                        align = err.align()
+                    ),
                 };
 
                 // If an allocation is created in an another const,
@@ -569,13 +593,54 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
 
     fn increment_const_eval_counter(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
         // The step limit has already been hit in a previous call to `increment_const_eval_counter`.
-        if ecx.machine.steps_remaining == 0 {
-            return Ok(());
-        }
 
-        ecx.machine.steps_remaining -= 1;
-        if ecx.machine.steps_remaining == 0 {
-            throw_exhaust!(StepLimitReached)
+        if let Some(new_steps) = ecx.machine.num_evaluated_steps.checked_add(1) {
+            let (limit, start) = if ecx.tcx.sess.opts.unstable_opts.tiny_const_eval_limit {
+                (TINY_LINT_TERMINATOR_LIMIT, TINY_LINT_TERMINATOR_LIMIT)
+            } else {
+                (LINT_TERMINATOR_LIMIT, PROGRESS_INDICATOR_START)
+            };
+
+            ecx.machine.num_evaluated_steps = new_steps;
+            // By default, we have a *deny* lint kicking in after some time
+            // to ensure `loop {}` doesn't just go forever.
+            // In case that lint got reduced, in particular for `--cap-lint` situations, we also
+            // have a hard warning shown every now and then for really long executions.
+            if new_steps == limit {
+                // By default, we stop after a million steps, but the user can disable this lint
+                // to be able to run until the heat death of the universe or power loss, whichever
+                // comes first.
+                let hir_id = ecx.best_lint_scope();
+                let is_error = ecx
+                    .tcx
+                    .lint_level_at_node(
+                        rustc_session::lint::builtin::LONG_RUNNING_CONST_EVAL,
+                        hir_id,
+                    )
+                    .0
+                    .is_error();
+                let span = ecx.cur_span();
+                ecx.tcx.emit_spanned_lint(
+                    rustc_session::lint::builtin::LONG_RUNNING_CONST_EVAL,
+                    hir_id,
+                    span,
+                    LongRunning { item_span: ecx.tcx.span },
+                );
+                // If this was a hard error, don't bother continuing evaluation.
+                if is_error {
+                    let guard = ecx
+                        .tcx
+                        .sess
+                        .delay_span_bug(span, "The deny lint should have already errored");
+                    throw_inval!(AlreadyReported(guard.into()));
+                }
+            } else if new_steps > start && new_steps.is_power_of_two() {
+                // Only report after a certain number of terminators have been evaluated and the
+                // current number of evaluated terminators is a power of 2. The latter gives us a cheap
+                // way to implement exponential backoff.
+                let span = ecx.cur_span();
+                ecx.tcx.sess.emit_warning(LongRunningWarn { span, item_span: ecx.tcx.span });
+            }
         }
 
         Ok(())
diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs
index 05be45fef13..6e462d3a1e9 100644
--- a/compiler/rustc_const_eval/src/const_eval/mod.rs
+++ b/compiler/rustc_const_eval/src/const_eval/mod.rs
@@ -2,10 +2,8 @@
 
 use crate::errors::MaxNumNodesInConstErr;
 use crate::interpret::{
-    intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, MemPlaceMeta,
-    Scalar,
+    intern_const_alloc_recursive, ConstValue, InternKind, InterpCx, InterpResult, Scalar,
 };
-use rustc_hir::Mutability;
 use rustc_middle::mir;
 use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId};
 use rustc_middle::ty::{self, TyCtxt};
@@ -75,17 +73,8 @@ pub(crate) fn eval_to_valtree<'tcx>(
             let global_const_id = cid.display(tcx);
             match err {
                 ValTreeCreationError::NodesOverflow => {
-                    let msg = format!(
-                        "maximum number of nodes exceeded in constant {}",
-                        &global_const_id
-                    );
-                    let mut diag = match tcx.hir().span_if_local(did) {
-                        Some(span) => {
-                            tcx.sess.create_err(MaxNumNodesInConstErr { span, global_const_id })
-                        }
-                        None => tcx.sess.struct_err(msg),
-                    };
-                    diag.emit();
+                    let span = tcx.hir().span_if_local(did);
+                    tcx.sess.emit_err(MaxNumNodesInConstErr { span, global_const_id });
 
                     Ok(None)
                 }
@@ -131,38 +120,3 @@ pub(crate) fn try_destructure_mir_constant<'tcx>(
 
     Ok(mir::DestructuredConstant { variant, fields })
 }
-
-#[instrument(skip(tcx), level = "debug")]
-pub(crate) fn deref_mir_constant<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    val: mir::ConstantKind<'tcx>,
-) -> mir::ConstantKind<'tcx> {
-    let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false);
-    let op = ecx.eval_mir_constant(&val, None, None).unwrap();
-    let mplace = ecx.deref_operand(&op).unwrap();
-    if let Some(alloc_id) = mplace.ptr.provenance {
-        assert_eq!(
-            tcx.global_alloc(alloc_id).unwrap_memory().0.0.mutability,
-            Mutability::Not,
-            "deref_mir_constant cannot be used with mutable allocations as \
-            that could allow pattern matching to observe mutable statics",
-        );
-    }
-
-    let ty = match mplace.meta {
-        MemPlaceMeta::None => mplace.layout.ty,
-        // In case of unsized types, figure out the real type behind.
-        MemPlaceMeta::Meta(scalar) => match mplace.layout.ty.kind() {
-            ty::Str => bug!("there's no sized equivalent of a `str`"),
-            ty::Slice(elem_ty) => tcx.mk_array(*elem_ty, scalar.to_target_usize(&tcx).unwrap()),
-            _ => bug!(
-                "type {} should not have metadata, but had {:?}",
-                mplace.layout.ty,
-                mplace.meta
-            ),
-        },
-    };
-
-    mir::ConstantKind::Val(op_to_const(&ecx, &mplace.into()), ty)
-}
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index f8b7cc6d7e1..eed3091d481 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -1,6 +1,24 @@
+use rustc_errors::{
+    DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, EmissionGuarantee, Handler,
+    IntoDiagnostic,
+};
 use rustc_hir::ConstContext;
-use rustc_macros::Diagnostic;
+use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
+use rustc_middle::mir::interpret::{
+    CheckInAllocMsg, ExpectedKind, InterpError, InvalidMetaKind, InvalidProgramInfo, PointerKind,
+    ResourceExhaustionInfo, UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo,
+};
+use rustc_middle::ty::{self, Ty};
 use rustc_span::Span;
+use rustc_target::abi::call::AdjustForForeignAbiError;
+use rustc_target::abi::{Size, WrappingRange};
+
+#[derive(Diagnostic)]
+#[diag(const_eval_dangling_ptr_in_final)]
+pub(crate) struct DanglingPtrInFinal {
+    #[primary_span]
+    pub span: Span,
+}
 
 #[derive(Diagnostic)]
 #[diag(const_eval_unstable_in_stable)]
@@ -92,7 +110,7 @@ pub(crate) struct TransientMutBorrowErrRaw {
 #[diag(const_eval_max_num_nodes_in_const)]
 pub(crate) struct MaxNumNodesInConstErr {
     #[primary_span]
-    pub span: Span,
+    pub span: Option<Span>,
     pub global_const_id: String,
 }
 
@@ -176,6 +194,14 @@ pub(crate) struct UnallowedInlineAsm {
 }
 
 #[derive(Diagnostic)]
+#[diag(const_eval_unsupported_untyped_pointer)]
+#[note]
+pub(crate) struct UnsupportedUntypedPointer {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(const_eval_interior_mutable_data_refer, code = "E0492")]
 pub(crate) struct InteriorMutableDataRefer {
     #[primary_span]
@@ -194,3 +220,649 @@ pub(crate) struct InteriorMutabilityBorrow {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(LintDiagnostic)]
+#[diag(const_eval_long_running)]
+#[note]
+pub struct LongRunning {
+    #[help]
+    pub item_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(const_eval_long_running)]
+pub struct LongRunningWarn {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    #[help]
+    pub item_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(const_eval_erroneous_constant)]
+pub(crate) struct ErroneousConstUsed {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Subdiagnostic)]
+#[note(const_eval_non_const_impl)]
+pub(crate) struct NonConstImplNote {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Subdiagnostic, PartialEq, Eq, Clone)]
+#[note(const_eval_frame_note)]
+pub struct FrameNote {
+    #[primary_span]
+    pub span: Span,
+    pub times: i32,
+    pub where_: &'static str,
+    pub instance: String,
+}
+
+#[derive(Subdiagnostic)]
+#[note(const_eval_raw_bytes)]
+pub struct RawBytesNote {
+    pub size: u64,
+    pub align: u64,
+    pub bytes: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(const_eval_for_loop_into_iter_non_const, code = "E0015")]
+pub struct NonConstForLoopIntoIter<'tcx> {
+    #[primary_span]
+    pub span: Span,
+    pub ty: Ty<'tcx>,
+    pub kind: ConstContext,
+}
+
+#[derive(Diagnostic)]
+#[diag(const_eval_question_branch_non_const, code = "E0015")]
+pub struct NonConstQuestionBranch<'tcx> {
+    #[primary_span]
+    pub span: Span,
+    pub ty: Ty<'tcx>,
+    pub kind: ConstContext,
+}
+
+#[derive(Diagnostic)]
+#[diag(const_eval_question_from_residual_non_const, code = "E0015")]
+pub struct NonConstQuestionFromResidual<'tcx> {
+    #[primary_span]
+    pub span: Span,
+    pub ty: Ty<'tcx>,
+    pub kind: ConstContext,
+}
+
+#[derive(Diagnostic)]
+#[diag(const_eval_try_block_from_output_non_const, code = "E0015")]
+pub struct NonConstTryBlockFromOutput<'tcx> {
+    #[primary_span]
+    pub span: Span,
+    pub ty: Ty<'tcx>,
+    pub kind: ConstContext,
+}
+
+#[derive(Diagnostic)]
+#[diag(const_eval_await_non_const, code = "E0015")]
+pub struct NonConstAwait<'tcx> {
+    #[primary_span]
+    pub span: Span,
+    pub ty: Ty<'tcx>,
+    pub kind: ConstContext,
+}
+
+#[derive(Diagnostic)]
+#[diag(const_eval_closure_non_const, code = "E0015")]
+pub struct NonConstClosure {
+    #[primary_span]
+    pub span: Span,
+    pub kind: ConstContext,
+    #[subdiagnostic]
+    pub note: Option<NonConstClosureNote>,
+}
+
+#[derive(Subdiagnostic)]
+pub enum NonConstClosureNote {
+    #[note(const_eval_closure_fndef_not_const)]
+    FnDef {
+        #[primary_span]
+        span: Span,
+    },
+    #[note(const_eval_fn_ptr_call)]
+    FnPtr,
+    #[note(const_eval_closure_call)]
+    Closure,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(const_eval_consider_dereferencing, applicability = "machine-applicable")]
+pub struct ConsiderDereferencing {
+    pub deref: String,
+    #[suggestion_part(code = "{deref}")]
+    pub span: Span,
+    #[suggestion_part(code = "{deref}")]
+    pub rhs_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(const_eval_operator_non_const, code = "E0015")]
+pub struct NonConstOperator {
+    #[primary_span]
+    pub span: Span,
+    pub kind: ConstContext,
+    #[subdiagnostic]
+    pub sugg: Option<ConsiderDereferencing>,
+}
+
+#[derive(Diagnostic)]
+#[diag(const_eval_deref_coercion_non_const, code = "E0015")]
+#[note]
+pub struct NonConstDerefCoercion<'tcx> {
+    #[primary_span]
+    pub span: Span,
+    pub ty: Ty<'tcx>,
+    pub kind: ConstContext,
+    pub target_ty: Ty<'tcx>,
+    #[note(const_eval_target_note)]
+    pub deref_target: Option<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(const_eval_live_drop, code = "E0493")]
+pub struct LiveDrop<'tcx> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub kind: ConstContext,
+    pub dropped_ty: Ty<'tcx>,
+    #[label(const_eval_dropped_at_label)]
+    pub dropped_at: Option<Span>,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(const_eval_align_check_failed)]
+pub struct AlignmentCheckFailed {
+    pub has: u64,
+    pub required: u64,
+    #[subdiagnostic]
+    pub frames: Vec<FrameNote>,
+}
+
+#[derive(Diagnostic)]
+#[diag(const_eval_error, code = "E0080")]
+pub struct ConstEvalError {
+    #[primary_span]
+    pub span: Span,
+    /// One of "const", "const_with_path", and "static"
+    pub error_kind: &'static str,
+    pub instance: String,
+    #[subdiagnostic]
+    pub frame_notes: Vec<FrameNote>,
+}
+
+#[derive(Diagnostic)]
+#[diag(const_eval_nullary_intrinsic_fail)]
+pub struct NullaryIntrinsicError {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(const_eval_undefined_behavior, code = "E0080")]
+pub struct UndefinedBehavior {
+    #[primary_span]
+    pub span: Span,
+    #[note(const_eval_undefined_behavior_note)]
+    pub ub_note: Option<()>,
+    #[subdiagnostic]
+    pub frames: Vec<FrameNote>,
+    #[subdiagnostic]
+    pub raw_bytes: RawBytesNote,
+}
+
+pub trait ReportErrorExt {
+    /// Returns the diagnostic message for this error.
+    fn diagnostic_message(&self) -> DiagnosticMessage;
+    fn add_args<G: EmissionGuarantee>(
+        self,
+        handler: &Handler,
+        builder: &mut DiagnosticBuilder<'_, G>,
+    );
+
+    fn debug(self) -> String
+    where
+        Self: Sized,
+    {
+        ty::tls::with(move |tcx| {
+            let mut builder = tcx.sess.struct_allow(DiagnosticMessage::Str(String::new().into()));
+            let handler = &tcx.sess.parse_sess.span_diagnostic;
+            let message = self.diagnostic_message();
+            self.add_args(handler, &mut builder);
+            let s = handler.eagerly_translate_to_string(message, builder.args());
+            builder.cancel();
+            s
+        })
+    }
+}
+
+fn bad_pointer_message(msg: CheckInAllocMsg, handler: &Handler) -> String {
+    use crate::fluent_generated::*;
+
+    let msg = match msg {
+        CheckInAllocMsg::DerefTest => const_eval_deref_test,
+        CheckInAllocMsg::MemoryAccessTest => const_eval_memory_access_test,
+        CheckInAllocMsg::PointerArithmeticTest => const_eval_pointer_arithmetic_test,
+        CheckInAllocMsg::OffsetFromTest => const_eval_offset_from_test,
+        CheckInAllocMsg::InboundsTest => const_eval_in_bounds_test,
+    };
+
+    handler.eagerly_translate_to_string(msg, [].into_iter())
+}
+
+impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
+    fn diagnostic_message(&self) -> DiagnosticMessage {
+        use crate::fluent_generated::*;
+        use UndefinedBehaviorInfo::*;
+        match self {
+            Ub(msg) => msg.clone().into(),
+            Unreachable => const_eval_unreachable,
+            BoundsCheckFailed { .. } => const_eval_bounds_check_failed,
+            DivisionByZero => const_eval_division_by_zero,
+            RemainderByZero => const_eval_remainder_by_zero,
+            DivisionOverflow => const_eval_division_overflow,
+            RemainderOverflow => const_eval_remainder_overflow,
+            PointerArithOverflow => const_eval_pointer_arithmetic_overflow,
+            InvalidMeta(InvalidMetaKind::SliceTooBig) => const_eval_invalid_meta_slice,
+            InvalidMeta(InvalidMetaKind::TooBig) => const_eval_invalid_meta,
+            UnterminatedCString(_) => const_eval_unterminated_c_string,
+            PointerUseAfterFree(_) => const_eval_pointer_use_after_free,
+            PointerOutOfBounds { ptr_size: Size::ZERO, .. } => const_eval_zst_pointer_out_of_bounds,
+            PointerOutOfBounds { .. } => const_eval_pointer_out_of_bounds,
+            DanglingIntPointer(0, _) => const_eval_dangling_null_pointer,
+            DanglingIntPointer(_, _) => const_eval_dangling_int_pointer,
+            AlignmentCheckFailed { .. } => const_eval_alignment_check_failed,
+            WriteToReadOnly(_) => const_eval_write_to_read_only,
+            DerefFunctionPointer(_) => const_eval_deref_function_pointer,
+            DerefVTablePointer(_) => const_eval_deref_vtable_pointer,
+            InvalidBool(_) => const_eval_invalid_bool,
+            InvalidChar(_) => const_eval_invalid_char,
+            InvalidTag(_) => const_eval_invalid_tag,
+            InvalidFunctionPointer(_) => const_eval_invalid_function_pointer,
+            InvalidVTablePointer(_) => const_eval_invalid_vtable_pointer,
+            InvalidStr(_) => const_eval_invalid_str,
+            InvalidUninitBytes(None) => const_eval_invalid_uninit_bytes_unknown,
+            InvalidUninitBytes(Some(_)) => const_eval_invalid_uninit_bytes,
+            DeadLocal => const_eval_dead_local,
+            ScalarSizeMismatch(_) => const_eval_scalar_size_mismatch,
+            UninhabitedEnumVariantWritten => const_eval_uninhabited_enum_variant_written,
+            Validation(e) => e.diagnostic_message(),
+            Custom(x) => (x.msg)(),
+        }
+    }
+
+    fn add_args<G: EmissionGuarantee>(
+        self,
+        handler: &Handler,
+        builder: &mut DiagnosticBuilder<'_, G>,
+    ) {
+        use UndefinedBehaviorInfo::*;
+        match self {
+            Ub(_)
+            | Unreachable
+            | DivisionByZero
+            | RemainderByZero
+            | DivisionOverflow
+            | RemainderOverflow
+            | PointerArithOverflow
+            | InvalidMeta(InvalidMetaKind::SliceTooBig)
+            | InvalidMeta(InvalidMetaKind::TooBig)
+            | InvalidUninitBytes(None)
+            | DeadLocal
+            | UninhabitedEnumVariantWritten => {}
+            BoundsCheckFailed { len, index } => {
+                builder.set_arg("len", len);
+                builder.set_arg("index", index);
+            }
+            UnterminatedCString(ptr) | InvalidFunctionPointer(ptr) | InvalidVTablePointer(ptr) => {
+                builder.set_arg("pointer", ptr);
+            }
+            PointerUseAfterFree(allocation) => {
+                builder.set_arg("allocation", allocation);
+            }
+            PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size, msg } => {
+                builder
+                    .set_arg("alloc_id", alloc_id)
+                    .set_arg("alloc_size", alloc_size.bytes())
+                    .set_arg("ptr_offset", ptr_offset)
+                    .set_arg("ptr_size", ptr_size.bytes())
+                    .set_arg("bad_pointer_message", bad_pointer_message(msg, handler));
+            }
+            DanglingIntPointer(ptr, msg) => {
+                if ptr != 0 {
+                    builder.set_arg("pointer", format!("{ptr:#x}[noalloc]"));
+                }
+
+                builder.set_arg("bad_pointer_message", bad_pointer_message(msg, handler));
+            }
+            AlignmentCheckFailed { required, has } => {
+                builder.set_arg("required", required.bytes());
+                builder.set_arg("has", has.bytes());
+            }
+            WriteToReadOnly(alloc) | DerefFunctionPointer(alloc) | DerefVTablePointer(alloc) => {
+                builder.set_arg("allocation", alloc);
+            }
+            InvalidBool(b) => {
+                builder.set_arg("value", format!("{b:02x}"));
+            }
+            InvalidChar(c) => {
+                builder.set_arg("value", format!("{c:08x}"));
+            }
+            InvalidTag(tag) => {
+                builder.set_arg("tag", format!("{tag:x}"));
+            }
+            InvalidStr(err) => {
+                builder.set_arg("err", format!("{err}"));
+            }
+            InvalidUninitBytes(Some((alloc, info))) => {
+                builder.set_arg("alloc", alloc);
+                builder.set_arg("access", info.access);
+                builder.set_arg("uninit", info.uninit);
+            }
+            ScalarSizeMismatch(info) => {
+                builder.set_arg("target_size", info.target_size);
+                builder.set_arg("data_size", info.data_size);
+            }
+            Validation(e) => e.add_args(handler, builder),
+            Custom(custom) => {
+                (custom.add_args)(&mut |name, value| {
+                    builder.set_arg(name, value);
+                });
+            }
+        }
+    }
+}
+
+impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> {
+    fn diagnostic_message(&self) -> DiagnosticMessage {
+        use crate::fluent_generated::*;
+        use rustc_middle::mir::interpret::ValidationErrorKind::*;
+        match self.kind {
+            PtrToUninhabited { ptr_kind: PointerKind::Box, .. } => const_eval_box_to_uninhabited,
+            PtrToUninhabited { ptr_kind: PointerKind::Ref, .. } => const_eval_ref_to_uninhabited,
+
+            PtrToStatic { ptr_kind: PointerKind::Box } => const_eval_box_to_static,
+            PtrToStatic { ptr_kind: PointerKind::Ref } => const_eval_ref_to_static,
+
+            PtrToMut { ptr_kind: PointerKind::Box } => const_eval_box_to_mut,
+            PtrToMut { ptr_kind: PointerKind::Ref } => const_eval_ref_to_mut,
+
+            ExpectedNonPtr { .. } => const_eval_expected_non_ptr,
+            MutableRefInConst => const_eval_mutable_ref_in_const,
+            NullFnPtr => const_eval_null_fn_ptr,
+            NeverVal => const_eval_never_val,
+            NullablePtrOutOfRange { .. } => const_eval_nullable_ptr_out_of_range,
+            PtrOutOfRange { .. } => const_eval_ptr_out_of_range,
+            OutOfRange { .. } => const_eval_out_of_range,
+            UnsafeCell => const_eval_unsafe_cell,
+            UninhabitedVal { .. } => const_eval_uninhabited_val,
+            InvalidEnumTag { .. } => const_eval_invalid_enum_tag,
+            UninitEnumTag => const_eval_uninit_enum_tag,
+            UninitStr => const_eval_uninit_str,
+            Uninit { expected: ExpectedKind::Bool } => const_eval_uninit_bool,
+            Uninit { expected: ExpectedKind::Reference } => const_eval_uninit_ref,
+            Uninit { expected: ExpectedKind::Box } => const_eval_uninit_box,
+            Uninit { expected: ExpectedKind::RawPtr } => const_eval_uninit_raw_ptr,
+            Uninit { expected: ExpectedKind::InitScalar } => const_eval_uninit_init_scalar,
+            Uninit { expected: ExpectedKind::Char } => const_eval_uninit_char,
+            Uninit { expected: ExpectedKind::Float } => const_eval_uninit_float,
+            Uninit { expected: ExpectedKind::Int } => const_eval_uninit_int,
+            Uninit { expected: ExpectedKind::FnPtr } => const_eval_uninit_fn_ptr,
+            UninitVal => const_eval_uninit,
+            InvalidVTablePtr { .. } => const_eval_invalid_vtable_ptr,
+            InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Box } => {
+                const_eval_invalid_box_slice_meta
+            }
+            InvalidMetaSliceTooLarge { ptr_kind: PointerKind::Ref } => {
+                const_eval_invalid_ref_slice_meta
+            }
+
+            InvalidMetaTooLarge { ptr_kind: PointerKind::Box } => const_eval_invalid_box_meta,
+            InvalidMetaTooLarge { ptr_kind: PointerKind::Ref } => const_eval_invalid_ref_meta,
+            UnalignedPtr { ptr_kind: PointerKind::Ref, .. } => const_eval_unaligned_ref,
+            UnalignedPtr { ptr_kind: PointerKind::Box, .. } => const_eval_unaligned_box,
+
+            NullPtr { ptr_kind: PointerKind::Box } => const_eval_null_box,
+            NullPtr { ptr_kind: PointerKind::Ref } => const_eval_null_ref,
+            DanglingPtrNoProvenance { ptr_kind: PointerKind::Box, .. } => {
+                const_eval_dangling_box_no_provenance
+            }
+            DanglingPtrNoProvenance { ptr_kind: PointerKind::Ref, .. } => {
+                const_eval_dangling_ref_no_provenance
+            }
+            DanglingPtrOutOfBounds { ptr_kind: PointerKind::Box } => {
+                const_eval_dangling_box_out_of_bounds
+            }
+            DanglingPtrOutOfBounds { ptr_kind: PointerKind::Ref } => {
+                const_eval_dangling_ref_out_of_bounds
+            }
+            DanglingPtrUseAfterFree { ptr_kind: PointerKind::Box } => {
+                const_eval_dangling_box_use_after_free
+            }
+            DanglingPtrUseAfterFree { ptr_kind: PointerKind::Ref } => {
+                const_eval_dangling_ref_use_after_free
+            }
+            InvalidBool { .. } => const_eval_validation_invalid_bool,
+            InvalidChar { .. } => const_eval_validation_invalid_char,
+            InvalidFnPtr { .. } => const_eval_invalid_fn_ptr,
+        }
+    }
+
+    fn add_args<G: EmissionGuarantee>(self, handler: &Handler, err: &mut DiagnosticBuilder<'_, G>) {
+        use crate::fluent_generated as fluent;
+        use rustc_middle::mir::interpret::ValidationErrorKind::*;
+
+        let message = if let Some(path) = self.path {
+            handler.eagerly_translate_to_string(
+                fluent::const_eval_invalid_value_with_path,
+                [("path".into(), DiagnosticArgValue::Str(path.into()))].iter().map(|(a, b)| (a, b)),
+            )
+        } else {
+            handler.eagerly_translate_to_string(fluent::const_eval_invalid_value, [].into_iter())
+        };
+
+        err.set_arg("front_matter", message);
+
+        fn add_range_arg<G: EmissionGuarantee>(
+            r: WrappingRange,
+            max_hi: u128,
+            handler: &Handler,
+            err: &mut DiagnosticBuilder<'_, G>,
+        ) {
+            let WrappingRange { start: lo, end: hi } = r;
+            assert!(hi <= max_hi);
+            let msg = if lo > hi {
+                fluent::const_eval_range_wrapping
+            } else if lo == hi {
+                fluent::const_eval_range_singular
+            } else if lo == 0 {
+                assert!(hi < max_hi, "should not be printing if the range covers everything");
+                fluent::const_eval_range_upper
+            } else if hi == max_hi {
+                assert!(lo > 0, "should not be printing if the range covers everything");
+                fluent::const_eval_range_lower
+            } else {
+                fluent::const_eval_range
+            };
+
+            let args = [
+                ("lo".into(), DiagnosticArgValue::Str(lo.to_string().into())),
+                ("hi".into(), DiagnosticArgValue::Str(hi.to_string().into())),
+            ];
+            let args = args.iter().map(|(a, b)| (a, b));
+            let message = handler.eagerly_translate_to_string(msg, args);
+            err.set_arg("in_range", message);
+        }
+
+        match self.kind {
+            PtrToUninhabited { ty, .. } | UninhabitedVal { ty } => {
+                err.set_arg("ty", ty);
+            }
+            ExpectedNonPtr { value }
+            | InvalidEnumTag { value }
+            | InvalidVTablePtr { value }
+            | InvalidBool { value }
+            | InvalidChar { value }
+            | InvalidFnPtr { value } => {
+                err.set_arg("value", value);
+            }
+            NullablePtrOutOfRange { range, max_value } | PtrOutOfRange { range, max_value } => {
+                add_range_arg(range, max_value, handler, err)
+            }
+            OutOfRange { range, max_value, value } => {
+                err.set_arg("value", value);
+                add_range_arg(range, max_value, handler, err);
+            }
+            UnalignedPtr { required_bytes, found_bytes, .. } => {
+                err.set_arg("required_bytes", required_bytes);
+                err.set_arg("found_bytes", found_bytes);
+            }
+            DanglingPtrNoProvenance { pointer, .. } => {
+                err.set_arg("pointer", pointer);
+            }
+            NullPtr { .. }
+            | PtrToStatic { .. }
+            | PtrToMut { .. }
+            | MutableRefInConst
+            | NullFnPtr
+            | NeverVal
+            | UnsafeCell
+            | UninitEnumTag
+            | UninitStr
+            | Uninit { .. }
+            | UninitVal
+            | InvalidMetaSliceTooLarge { .. }
+            | InvalidMetaTooLarge { .. }
+            | DanglingPtrUseAfterFree { .. }
+            | DanglingPtrOutOfBounds { .. } => {}
+        }
+    }
+}
+
+impl ReportErrorExt for UnsupportedOpInfo {
+    fn diagnostic_message(&self) -> DiagnosticMessage {
+        use crate::fluent_generated::*;
+        match self {
+            UnsupportedOpInfo::Unsupported(s) => s.clone().into(),
+            UnsupportedOpInfo::PartialPointerOverwrite(_) => const_eval_partial_pointer_overwrite,
+            UnsupportedOpInfo::PartialPointerCopy(_) => const_eval_partial_pointer_copy,
+            UnsupportedOpInfo::ReadPointerAsBytes => const_eval_read_pointer_as_bytes,
+            UnsupportedOpInfo::ThreadLocalStatic(_) => const_eval_thread_local_static,
+            UnsupportedOpInfo::ReadExternStatic(_) => const_eval_read_extern_static,
+        }
+    }
+    fn add_args<G: EmissionGuarantee>(self, _: &Handler, builder: &mut DiagnosticBuilder<'_, G>) {
+        use crate::fluent_generated::*;
+
+        use UnsupportedOpInfo::*;
+        if let ReadPointerAsBytes | PartialPointerOverwrite(_) | PartialPointerCopy(_) = self {
+            builder.help(const_eval_ptr_as_bytes_1);
+            builder.help(const_eval_ptr_as_bytes_2);
+        }
+        match self {
+            Unsupported(_) | ReadPointerAsBytes => {}
+            PartialPointerOverwrite(ptr) | PartialPointerCopy(ptr) => {
+                builder.set_arg("ptr", ptr);
+            }
+            ThreadLocalStatic(did) | ReadExternStatic(did) => {
+                builder.set_arg("did", format!("{did:?}"));
+            }
+        }
+    }
+}
+
+impl<'tcx> ReportErrorExt for InterpError<'tcx> {
+    fn diagnostic_message(&self) -> DiagnosticMessage {
+        match self {
+            InterpError::UndefinedBehavior(ub) => ub.diagnostic_message(),
+            InterpError::Unsupported(e) => e.diagnostic_message(),
+            InterpError::InvalidProgram(e) => e.diagnostic_message(),
+            InterpError::ResourceExhaustion(e) => e.diagnostic_message(),
+            InterpError::MachineStop(e) => e.diagnostic_message(),
+        }
+    }
+    fn add_args<G: EmissionGuarantee>(
+        self,
+        handler: &Handler,
+        builder: &mut DiagnosticBuilder<'_, G>,
+    ) {
+        match self {
+            InterpError::UndefinedBehavior(ub) => ub.add_args(handler, builder),
+            InterpError::Unsupported(e) => e.add_args(handler, builder),
+            InterpError::InvalidProgram(e) => e.add_args(handler, builder),
+            InterpError::ResourceExhaustion(e) => e.add_args(handler, builder),
+            InterpError::MachineStop(e) => e.add_args(&mut |name, value| {
+                builder.set_arg(name, value);
+            }),
+        }
+    }
+}
+
+impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> {
+    fn diagnostic_message(&self) -> DiagnosticMessage {
+        use crate::fluent_generated::*;
+        match self {
+            InvalidProgramInfo::TooGeneric => const_eval_too_generic,
+            InvalidProgramInfo::AlreadyReported(_) => const_eval_already_reported,
+            InvalidProgramInfo::Layout(e) => e.diagnostic_message(),
+            InvalidProgramInfo::FnAbiAdjustForForeignAbi(_) => {
+                rustc_middle::error::middle_adjust_for_foreign_abi_error
+            }
+            InvalidProgramInfo::SizeOfUnsizedType(_) => const_eval_size_of_unsized,
+            InvalidProgramInfo::UninitUnsizedLocal => const_eval_uninit_unsized_local,
+        }
+    }
+    fn add_args<G: EmissionGuarantee>(
+        self,
+        handler: &Handler,
+        builder: &mut DiagnosticBuilder<'_, G>,
+    ) {
+        match self {
+            InvalidProgramInfo::TooGeneric
+            | InvalidProgramInfo::AlreadyReported(_)
+            | InvalidProgramInfo::UninitUnsizedLocal => {}
+            InvalidProgramInfo::Layout(e) => {
+                let diag: DiagnosticBuilder<'_, ()> = e.into_diagnostic().into_diagnostic(handler);
+                for (name, val) in diag.args() {
+                    builder.set_arg(name.clone(), val.clone());
+                }
+                diag.cancel();
+            }
+            InvalidProgramInfo::FnAbiAdjustForForeignAbi(
+                AdjustForForeignAbiError::Unsupported { arch, abi },
+            ) => {
+                builder.set_arg("arch", arch);
+                builder.set_arg("abi", abi.name());
+            }
+            InvalidProgramInfo::SizeOfUnsizedType(ty) => {
+                builder.set_arg("ty", ty);
+            }
+        }
+    }
+}
+
+impl ReportErrorExt for ResourceExhaustionInfo {
+    fn diagnostic_message(&self) -> DiagnosticMessage {
+        use crate::fluent_generated::*;
+        match self {
+            ResourceExhaustionInfo::StackFrameLimitReached => const_eval_stack_frame_limit_reached,
+            ResourceExhaustionInfo::MemoryExhausted => const_eval_memory_exhausted,
+            ResourceExhaustionInfo::AddressSpaceFull => const_eval_address_space_full,
+        }
+    }
+    fn add_args<G: EmissionGuarantee>(self, _: &Handler, _: &mut DiagnosticBuilder<'_, G>) {}
+}
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index 163e3f86993..b4db3dff3ff 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -14,6 +14,8 @@ use super::{
     util::ensure_monomorphic_enough, FnVal, ImmTy, Immediate, InterpCx, Machine, OpTy, PlaceTy,
 };
 
+use crate::fluent_generated as fluent;
+
 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     pub fn cast(
         &mut self,
@@ -138,12 +140,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 assert!(src.layout.is_sized());
                 assert!(dest.layout.is_sized());
                 if src.layout.size != dest.layout.size {
-                    throw_ub_format!(
-                        "transmuting from {}-byte type to {}-byte type: `{}` -> `{}`",
-                        src.layout.size.bytes(),
-                        dest.layout.size.bytes(),
-                        src.layout.ty,
-                        dest.layout.ty,
+                    let src_bytes = src.layout.size.bytes();
+                    let dest_bytes = dest.layout.size.bytes();
+                    let src_ty = format!("{}", src.layout.ty);
+                    let dest_ty = format!("{}", dest.layout.ty);
+                    throw_ub_custom!(
+                        fluent::const_eval_invalid_transmute,
+                        src_bytes = src_bytes,
+                        dest_bytes = dest_bytes,
+                        src = src_ty,
+                        dest = dest_ty,
                     );
                 }
 
@@ -363,7 +369,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let old_vptr = old_vptr.to_pointer(self)?;
                 let (ty, old_trait) = self.get_ptr_vtable(old_vptr)?;
                 if old_trait != data_a.principal() {
-                    throw_ub_format!("upcast on a pointer whose vtable does not match its type");
+                    throw_ub_custom!(fluent::const_eval_upcast_mismatch);
                 }
                 let new_vptr = self.get_vtable_ptr(ty, data_b.principal())?;
                 self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest)
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 91ccdef7215..36606ff69a6 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -1,13 +1,13 @@
 use std::cell::Cell;
-use std::fmt;
-use std::mem;
+use std::{fmt, mem};
 
 use either::{Either, Left, Right};
 
+use hir::CRATE_HIR_ID;
 use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData};
 use rustc_index::IndexVec;
 use rustc_middle::mir;
-use rustc_middle::mir::interpret::{ErrorHandled, InterpError, ReportedErrorInfo};
+use rustc_middle::mir::interpret::{ErrorHandled, InterpError, InvalidMetaKind, ReportedErrorInfo};
 use rustc_middle::query::TyCtxtAt;
 use rustc_middle::ty::layout::{
     self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOf, LayoutOfHelpers,
@@ -24,6 +24,8 @@ use super::{
     MemPlaceMeta, Memory, MemoryKind, Operand, Place, PlaceTy, PointerArithmetic, Provenance,
     Scalar, StackPopJump,
 };
+use crate::errors::{self, ErroneousConstUsed};
+use crate::fluent_generated as fluent;
 use crate::util;
 
 pub struct InterpCx<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
@@ -246,6 +248,7 @@ impl<'mir, 'tcx, Prov: Provenance, Extra> Frame<'mir, 'tcx, Prov, Extra> {
     }
 }
 
+// FIXME: only used by miri, should be removed once translatable.
 impl<'tcx> fmt::Display for FrameInfo<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         ty::tls::with(|tcx| {
@@ -263,6 +266,21 @@ impl<'tcx> fmt::Display for FrameInfo<'tcx> {
     }
 }
 
+impl<'tcx> FrameInfo<'tcx> {
+    pub fn as_note(&self, tcx: TyCtxt<'tcx>) -> errors::FrameNote {
+        let span = self.span;
+        if tcx.def_key(self.instance.def_id()).disambiguated_data.data == DefPathData::ClosureExpr {
+            errors::FrameNote { where_: "closure", span, instance: String::new(), times: 0 }
+        } else {
+            let instance = format!("{}", self.instance);
+            // Note: this triggers a `good_path_bug` state, which means that if we ever get here
+            // we must emit a diagnostic. We should never display a `FrameInfo` unless we
+            // actually want to emit a warning or error to the user.
+            errors::FrameNote { where_: "instance", span, instance, times: 0 }
+        }
+    }
+}
+
 impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> HasDataLayout for InterpCx<'mir, 'tcx, M> {
     #[inline]
     fn data_layout(&self) -> &TargetDataLayout {
@@ -406,6 +424,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     }
 
     #[inline(always)]
+    /// Find the first stack frame that is within the current crate, if any, otherwise return the crate's HirId
+    pub fn best_lint_scope(&self) -> hir::HirId {
+        self.stack()
+            .iter()
+            .find_map(|frame| frame.body.source.def_id().as_local())
+            .map_or(CRATE_HIR_ID, |def_id| self.tcx.hir().local_def_id_to_hir_id(def_id))
+    }
+
+    #[inline(always)]
     pub(crate) fn stack(&self) -> &[Frame<'mir, 'tcx, M::Provenance, M::FrameExtra>] {
         M::stack(self)
     }
@@ -610,7 +637,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
                 // Check if this brought us over the size limit.
                 if size > self.max_size_of_val() {
-                    throw_ub!(InvalidMeta("total size is bigger than largest supported object"));
+                    throw_ub!(InvalidMeta(InvalidMetaKind::TooBig));
                 }
                 Ok(Some((size, align)))
             }
@@ -628,7 +655,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let size = elem.size.bytes().saturating_mul(len); // we rely on `max_size_of_val` being smaller than `u64::MAX`.
                 let size = Size::from_bytes(size);
                 if size > self.max_size_of_val() {
-                    throw_ub!(InvalidMeta("slice is bigger than largest supported object"));
+                    throw_ub!(InvalidMeta(InvalidMetaKind::SliceTooBig));
                 }
                 Ok(Some((size, elem.align.abi)))
             }
@@ -736,7 +763,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             mir::UnwindAction::Cleanup(block) => Left(mir::Location { block, statement_index: 0 }),
             mir::UnwindAction::Continue => Right(self.frame_mut().body.span),
             mir::UnwindAction::Unreachable => {
-                throw_ub_format!("unwinding past a stack frame that does not allow unwinding")
+                throw_ub_custom!(fluent::const_eval_unreachable_unwind);
             }
             mir::UnwindAction::Terminate => {
                 self.frame_mut().loc = Right(self.frame_mut().body.span);
@@ -775,7 +802,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
         );
         if unwinding && self.frame_idx() == 0 {
-            throw_ub_format!("unwinding past the topmost frame of the stack");
+            throw_ub_custom!(fluent::const_eval_unwind_past_top);
         }
 
         // Copy return value. Must of course happen *before* we deallocate the locals.
@@ -863,7 +890,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // StorageLive expects the local to be dead, and marks it live.
         let old = mem::replace(&mut self.frame_mut().locals[local].value, local_val);
         if !matches!(old, LocalValue::Dead) {
-            throw_ub_format!("StorageLive on a local that was already live");
+            throw_ub_custom!(fluent::const_eval_double_storage_live);
         }
         Ok(())
     }
@@ -906,7 +933,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 ErrorHandled::Reported(err) => {
                     if !err.is_tainted_by_errors() && let Some(span) = span {
                         // To make it easier to figure out where this error comes from, also add a note at the current location.
-                        self.tcx.sess.span_note_without_error(span, "erroneous constant used");
+                        self.tcx.sess.emit_note(ErroneousConstUsed { span });
                     }
                     err_inval!(AlreadyReported(err))
                 }
diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs
index c2b82ba9b07..7b11ad33091 100644
--- a/compiler/rustc_const_eval/src/interpret/intern.rs
+++ b/compiler/rustc_const_eval/src/interpret/intern.rs
@@ -28,6 +28,7 @@ use super::{
     ValueVisitor,
 };
 use crate::const_eval;
+use crate::errors::{DanglingPtrInFinal, UnsupportedUntypedPointer};
 
 pub trait CompileTimeMachine<'mir, 'tcx, T> = Machine<
         'mir,
@@ -320,10 +321,12 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory
     }
 }
 
+/// How a constant value should be interned.
 #[derive(Copy, Clone, Debug, PartialEq, Hash, Eq)]
 pub enum InternKind {
     /// The `mutability` of the static, ignoring the type which may have interior mutability.
     Static(hir::Mutability),
+    /// A `const` item
     Constant,
     Promoted,
 }
@@ -388,8 +391,7 @@ pub fn intern_const_alloc_recursive<
                 ecx.tcx.sess.delay_span_bug(
                     ecx.tcx.span,
                     format!(
-                        "error during interning should later cause validation failure: {}",
-                        error
+                        "error during interning should later cause validation failure: {error:?}"
                     ),
                 );
             }
@@ -425,14 +427,16 @@ pub fn intern_const_alloc_recursive<
                     // immutability is so important.
                     alloc.mutability = Mutability::Not;
                 }
+                // If it's a constant, we should not have any "leftovers" as everything
+                // is tracked by const-checking.
+                // FIXME: downgrade this to a warning? It rejects some legitimate consts,
+                // such as `const CONST_RAW: *const Vec<i32> = &Vec::new() as *const _;`.
+                //
+                // NOTE: it looks likes this code path is only reachable when we try to intern
+                // something that cannot be promoted, which in constants means values that have
+                // drop glue, such as the example above.
                 InternKind::Constant => {
-                    // If it's a constant, we should not have any "leftovers" as everything
-                    // is tracked by const-checking.
-                    // FIXME: downgrade this to a warning? It rejects some legitimate consts,
-                    // such as `const CONST_RAW: *const Vec<i32> = &Vec::new() as *const _;`.
-                    ecx.tcx
-                        .sess
-                        .span_err(ecx.tcx.span, "untyped pointers are not allowed in constant");
+                    ecx.tcx.sess.emit_err(UnsupportedUntypedPointer { span: ecx.tcx.span });
                     // For better errors later, mark the allocation as immutable.
                     alloc.mutability = Mutability::Not;
                 }
@@ -447,10 +451,7 @@ pub fn intern_const_alloc_recursive<
         } else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) {
             // Codegen does not like dangling pointers, and generally `tcx` assumes that
             // all allocations referenced anywhere actually exist. So, make sure we error here.
-            let reported = ecx
-                .tcx
-                .sess
-                .span_err(ecx.tcx.span, "encountered dangling pointer in final constant");
+            let reported = ecx.tcx.sess.emit_err(DanglingPtrInFinal { span: ecx.tcx.span });
             return Err(reported);
         } else if ecx.tcx.try_get_global_alloc(alloc_id).is_none() {
             // We have hit an `AllocId` that is neither in local or global memory and isn't
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index a77c699c22f..fb24cf48a9a 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -22,6 +22,8 @@ use super::{
     Pointer,
 };
 
+use crate::fluent_generated as fluent;
+
 mod caller_location;
 
 fn numeric_intrinsic<Prov>(name: Symbol, bits: u128, kind: Primitive) -> Scalar<Prov> {
@@ -198,15 +200,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         ty
                     ),
                 };
-                let (nonzero, intrinsic_name) = match intrinsic_name {
+                let (nonzero, actual_intrinsic_name) = match intrinsic_name {
                     sym::cttz_nonzero => (true, sym::cttz),
                     sym::ctlz_nonzero => (true, sym::ctlz),
                     other => (false, other),
                 };
                 if nonzero && bits == 0 {
-                    throw_ub_format!("`{}_nonzero` called on 0", intrinsic_name);
+                    throw_ub_custom!(
+                        fluent::const_eval_call_nonzero_intrinsic,
+                        name = intrinsic_name,
+                    );
                 }
-                let out_val = numeric_intrinsic(intrinsic_name, bits, kind);
+                let out_val = numeric_intrinsic(actual_intrinsic_name, bits, kind);
                 self.write_scalar(out_val, dest)?;
             }
             sym::saturating_add | sym::saturating_sub => {
@@ -253,9 +258,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     let layout = self.layout_of(substs.type_at(0))?;
                     let r_val = r.to_scalar().to_bits(layout.size)?;
                     if let sym::unchecked_shl | sym::unchecked_shr = intrinsic_name {
-                        throw_ub_format!("overflowing shift by {} in `{}`", r_val, intrinsic_name);
+                        throw_ub_custom!(
+                            fluent::const_eval_overflow_shift,
+                            val = r_val,
+                            name = intrinsic_name
+                        );
                     } else {
-                        throw_ub_format!("overflow executing `{}`", intrinsic_name);
+                        throw_ub_custom!(fluent::const_eval_overflow, name = intrinsic_name);
                     }
                 }
                 self.write_scalar(val, dest)?;
@@ -314,17 +323,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         (Err(_), _) | (_, Err(_)) => {
                             // We managed to find a valid allocation for one pointer, but not the other.
                             // That means they are definitely not pointing to the same allocation.
-                            throw_ub_format!(
-                                "`{}` called on pointers into different allocations",
-                                intrinsic_name
+                            throw_ub_custom!(
+                                fluent::const_eval_different_allocations,
+                                name = intrinsic_name,
                             );
                         }
                         (Ok((a_alloc_id, a_offset, _)), Ok((b_alloc_id, b_offset, _))) => {
                             // Found allocation for both. They must be into the same allocation.
                             if a_alloc_id != b_alloc_id {
-                                throw_ub_format!(
-                                    "`{}` called on pointers into different allocations",
-                                    intrinsic_name
+                                throw_ub_custom!(
+                                    fluent::const_eval_different_allocations,
+                                    name = intrinsic_name,
                                 );
                             }
                             // Use these offsets for distance calculation.
@@ -344,11 +353,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     if overflowed {
                         // a < b
                         if intrinsic_name == sym::ptr_offset_from_unsigned {
-                            throw_ub_format!(
-                                "`{}` called when first pointer has smaller offset than second: {} < {}",
-                                intrinsic_name,
-                                a_offset,
-                                b_offset,
+                            throw_ub_custom!(
+                                fluent::const_eval_unsigned_offset_from_overflow,
+                                a_offset = a_offset,
+                                b_offset = b_offset,
                             );
                         }
                         // The signed form of the intrinsic allows this. If we interpret the
@@ -356,9 +364,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         // seems *positive*, they were more than isize::MAX apart.
                         let dist = val.to_target_isize(self)?;
                         if dist >= 0 {
-                            throw_ub_format!(
-                                "`{}` called when first pointer is too far before second",
-                                intrinsic_name
+                            throw_ub_custom!(
+                                fluent::const_eval_offset_from_underflow,
+                                name = intrinsic_name,
                             );
                         }
                         dist
@@ -368,9 +376,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         // If converting to isize produced a *negative* result, we had an overflow
                         // because they were more than isize::MAX apart.
                         if dist < 0 {
-                            throw_ub_format!(
-                                "`{}` called when first pointer is too far ahead of second",
-                                intrinsic_name
+                            throw_ub_custom!(
+                                fluent::const_eval_offset_from_overflow,
+                                name = intrinsic_name,
                             );
                         }
                         dist
@@ -513,7 +521,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let op = self.eval_operand(op, None)?;
                 let cond = self.read_scalar(&op)?.to_bool()?;
                 if !cond {
-                    throw_ub_format!("`assume` called with `false`");
+                    throw_ub_custom!(fluent::const_eval_assume_false);
                 }
                 Ok(())
             }
@@ -542,7 +550,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let (res, overflow, _ty) = self.overflowing_binary_op(BinOp::Rem, &a, &b)?;
         assert!(!overflow); // All overflow is UB, so this should never return on overflow.
         if res.assert_bits(a.layout.size) != 0 {
-            throw_ub_format!("exact_div: {} cannot be divided by {} without remainder", a, b)
+            throw_ub_custom!(
+                fluent::const_eval_exact_div_has_remainder,
+                a = format!("{a}"),
+                b = format!("{b}")
+            )
         }
         // `Rem` says this is all right, so we can let `Div` do its job.
         self.binop_ignore_overflow(BinOp::Div, &a, &b, dest)
@@ -638,9 +650,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max),
         // but no actual allocation can be big enough for the difference to be noticeable.
         let size = size.checked_mul(count, self).ok_or_else(|| {
-            err_ub_format!(
-                "overflow computing total size of `{}`",
-                if nonoverlapping { "copy_nonoverlapping" } else { "copy" }
+            err_ub_custom!(
+                fluent::const_eval_size_overflow,
+                name = if nonoverlapping { "copy_nonoverlapping" } else { "copy" }
             )
         })?;
 
@@ -664,10 +676,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
         // `checked_mul` enforces a too small bound (the correct one would probably be target_isize_max),
         // but no actual allocation can be big enough for the difference to be noticeable.
-        let len = layout
-            .size
-            .checked_mul(count, self)
-            .ok_or_else(|| err_ub_format!("overflow computing total size of `write_bytes`"))?;
+        let len = layout.size.checked_mul(count, self).ok_or_else(|| {
+            err_ub_custom!(fluent::const_eval_size_overflow, name = "write_bytes")
+        })?;
 
         let bytes = std::iter::repeat(byte).take(len.bytes_usize());
         self.write_bytes_ptr(dst, bytes)
@@ -691,7 +702,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 return Ok(&[]);
             };
             if alloc_ref.has_provenance() {
-                throw_ub_format!("`raw_eq` on bytes with provenance");
+                throw_ub_custom!(fluent::const_eval_raw_eq_with_provenance);
             }
             alloc_ref.get_bytes_strip_provenance()
         };
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index d5b6a581a79..1125d8d1f0e 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -19,6 +19,7 @@ use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TyCtxt};
 use rustc_target::abi::{Align, HasDataLayout, Size};
 
 use crate::const_eval::CheckAlignment;
+use crate::fluent_generated as fluent;
 
 use super::{
     alloc_range, AllocBytes, AllocId, AllocMap, AllocRange, Allocation, CheckInAllocMsg,
@@ -200,7 +201,11 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         align: Align,
         kind: MemoryKind<M::MemoryKind>,
     ) -> InterpResult<'tcx, Pointer<M::Provenance>> {
-        let alloc = Allocation::uninit(size, align, M::PANIC_ON_ALLOC_FAIL)?;
+        let alloc = if M::PANIC_ON_ALLOC_FAIL {
+            Allocation::uninit(size, align)
+        } else {
+            Allocation::try_uninit(size, align)?
+        };
         self.allocate_raw_ptr(alloc, kind)
     }
 
@@ -242,9 +247,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     ) -> InterpResult<'tcx, Pointer<M::Provenance>> {
         let (alloc_id, offset, _prov) = self.ptr_get_alloc_id(ptr)?;
         if offset.bytes() != 0 {
-            throw_ub_format!(
-                "reallocating {:?} which does not point to the beginning of an object",
-                ptr
+            throw_ub_custom!(
+                fluent::const_eval_realloc_or_alloc_with_offset,
+                ptr = format!("{ptr:?}"),
+                kind = "realloc"
             );
         }
 
@@ -280,9 +286,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         trace!("deallocating: {alloc_id:?}");
 
         if offset.bytes() != 0 {
-            throw_ub_format!(
-                "deallocating {:?} which does not point to the beginning of an object",
-                ptr
+            throw_ub_custom!(
+                fluent::const_eval_realloc_or_alloc_with_offset,
+                ptr = format!("{ptr:?}"),
+                kind = "dealloc",
             );
         }
 
@@ -290,13 +297,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             // Deallocating global memory -- always an error
             return Err(match self.tcx.try_get_global_alloc(alloc_id) {
                 Some(GlobalAlloc::Function(..)) => {
-                    err_ub_format!("deallocating {alloc_id:?}, which is a function")
+                    err_ub_custom!(
+                        fluent::const_eval_invalid_dealloc,
+                        alloc_id = alloc_id,
+                        kind = "fn",
+                    )
                 }
                 Some(GlobalAlloc::VTable(..)) => {
-                    err_ub_format!("deallocating {alloc_id:?}, which is a vtable")
+                    err_ub_custom!(
+                        fluent::const_eval_invalid_dealloc,
+                        alloc_id = alloc_id,
+                        kind = "vtable",
+                    )
                 }
                 Some(GlobalAlloc::Static(..) | GlobalAlloc::Memory(..)) => {
-                    err_ub_format!("deallocating {alloc_id:?}, which is static memory")
+                    err_ub_custom!(
+                        fluent::const_eval_invalid_dealloc,
+                        alloc_id = alloc_id,
+                        kind = "static_mem"
+                    )
                 }
                 None => err_ub!(PointerUseAfterFree(alloc_id)),
             }
@@ -304,21 +323,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         };
 
         if alloc.mutability.is_not() {
-            throw_ub_format!("deallocating immutable allocation {alloc_id:?}");
+            throw_ub_custom!(fluent::const_eval_dealloc_immutable, alloc = alloc_id,);
         }
         if alloc_kind != kind {
-            throw_ub_format!(
-                "deallocating {alloc_id:?}, which is {alloc_kind} memory, using {kind} deallocation operation"
+            throw_ub_custom!(
+                fluent::const_eval_dealloc_kind_mismatch,
+                alloc = alloc_id,
+                alloc_kind = format!("{alloc_kind}"),
+                kind = format!("{kind}"),
             );
         }
         if let Some((size, align)) = old_size_and_align {
             if size != alloc.size() || align != alloc.align {
-                throw_ub_format!(
-                    "incorrect layout on deallocation: {alloc_id:?} has size {} and alignment {}, but gave size {} and alignment {}",
-                    alloc.size().bytes(),
-                    alloc.align.bytes(),
-                    size.bytes(),
-                    align.bytes(),
+                throw_ub_custom!(
+                    fluent::const_eval_dealloc_incorrect_layout,
+                    alloc = alloc_id,
+                    size = alloc.size().bytes(),
+                    align = alloc.align.bytes(),
+                    size_found = size.bytes(),
+                    align_found = align.bytes(),
                 )
             }
         }
@@ -1166,7 +1189,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     if (src_offset <= dest_offset && src_offset + size > dest_offset)
                         || (dest_offset <= src_offset && dest_offset + size > src_offset)
                     {
-                        throw_ub_format!("copy_nonoverlapping called on overlapping ranges")
+                        throw_ub_custom!(fluent::const_eval_copy_nonoverlapping_overlapping);
                     }
                 }
 
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 586e8f063ee..7269ff8d53c 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -15,6 +15,7 @@ use super::{
     FnVal, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemoryKind, OpTy, Operand,
     PlaceTy, Scalar, StackPopCleanup,
 };
+use crate::fluent_generated as fluent;
 
 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     pub(super) fn eval_terminator(
@@ -172,7 +173,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             InlineAsm { template, ref operands, options, destination, .. } => {
                 M::eval_inline_asm(self, template, operands, options)?;
                 if options.contains(InlineAsmOptions::NORETURN) {
-                    throw_ub_format!("returned from noreturn inline assembly");
+                    throw_ub_custom!(fluent::const_eval_noreturn_asm_returned);
                 }
                 self.go_to_block(
                     destination
@@ -288,15 +289,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             return Ok(());
         }
         // Find next caller arg.
-        let (caller_arg, caller_abi) = caller_args.next().ok_or_else(|| {
-            err_ub_format!("calling a function with fewer arguments than it requires")
-        })?;
+        let Some((caller_arg, caller_abi)) = caller_args.next() else {
+            throw_ub_custom!(fluent::const_eval_not_enough_caller_args);
+        };
         // Now, check
         if !Self::check_argument_compat(caller_abi, callee_abi) {
-            throw_ub_format!(
-                "calling a function with argument of type {:?} passing data of type {:?}",
-                callee_arg.layout.ty,
-                caller_arg.layout.ty
+            let callee_ty = format!("{}", callee_arg.layout.ty);
+            let caller_ty = format!("{}", caller_arg.layout.ty);
+            throw_ub_custom!(
+                fluent::const_eval_incompatible_types,
+                callee_ty = callee_ty,
+                caller_ty = caller_ty,
             )
         }
         // Special handling for unsized parameters.
@@ -398,10 +401,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
                 if M::enforce_abi(self) {
                     if caller_fn_abi.conv != callee_fn_abi.conv {
-                        throw_ub_format!(
-                            "calling a function with calling convention {:?} using calling convention {:?}",
-                            callee_fn_abi.conv,
-                            caller_fn_abi.conv
+                        throw_ub_custom!(
+                            fluent::const_eval_incompatible_calling_conventions,
+                            callee_conv = format!("{:?}", callee_fn_abi.conv),
+                            caller_conv = format!("{:?}", caller_fn_abi.conv),
                         )
                     }
                 }
@@ -508,15 +511,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         "mismatch between callee ABI and callee body arguments"
                     );
                     if caller_args.next().is_some() {
-                        throw_ub_format!("calling a function with more arguments than it expected")
+                        throw_ub_custom!(fluent::const_eval_too_many_caller_args);
                     }
                     // Don't forget to check the return type!
                     if !Self::check_argument_compat(&caller_fn_abi.ret, &callee_fn_abi.ret) {
-                        throw_ub_format!(
-                            "calling a function with return type {:?} passing \
-                                    return place of type {:?}",
-                            callee_fn_abi.ret.layout.ty,
-                            caller_fn_abi.ret.layout.ty,
+                        let callee_ty = format!("{}", callee_fn_abi.ret.layout.ty);
+                        let caller_ty = format!("{}", caller_fn_abi.ret.layout.ty);
+                        throw_ub_custom!(
+                            fluent::const_eval_incompatible_return_types,
+                            callee_ty = callee_ty,
+                            caller_ty = caller_ty,
                         )
                     }
                 };
@@ -587,9 +591,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     let (recv, vptr) = self.unpack_dyn_star(&receiver_place.into())?;
                     let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?;
                     if dyn_trait != data.principal() {
-                        throw_ub_format!(
-                            "`dyn*` call on a pointer whose vtable does not match its type"
-                        );
+                        throw_ub_custom!(fluent::const_eval_dyn_star_call_vtable_mismatch);
                     }
                     let recv = recv.assert_mem_place(); // we passed an MPlaceTy to `unpack_dyn_star` so we definitely still have one
 
@@ -609,9 +611,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     let vptr = receiver_place.meta.unwrap_meta().to_pointer(self)?;
                     let (dyn_ty, dyn_trait) = self.get_ptr_vtable(vptr)?;
                     if dyn_trait != data.principal() {
-                        throw_ub_format!(
-                            "`dyn` call on a pointer whose vtable does not match its type"
-                        );
+                        throw_ub_custom!(fluent::const_eval_dyn_call_vtable_mismatch);
                     }
 
                     // It might be surprising that we use a pointer as the receiver even if this
@@ -623,7 +623,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 // Now determine the actual method to call. We can do that in two different ways and
                 // compare them to ensure everything fits.
                 let Some(ty::VtblEntry::Method(fn_inst)) = self.get_vtable_entries(vptr)?.get(idx).copied() else {
-                    throw_ub_format!("`dyn` call trying to call something that is not a method")
+                    // FIXME(fee1-dead) these could be variants of the UB info enum instead of this
+                    throw_ub_custom!(fluent::const_eval_dyn_call_not_a_method);
                 };
                 trace!("Virtual call dispatches to {fn_inst:#?}");
                 if cfg!(debug_assertions) {
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 01b77289937..21c655988a0 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -4,7 +4,7 @@
 //! That's useful because it means other passes (e.g. promotion) can rely on `const`s
 //! to be const-safe.
 
-use std::fmt::{Display, Write};
+use std::fmt::Write;
 use std::num::NonZeroUsize;
 
 use either::{Left, Right};
@@ -12,7 +12,10 @@ use either::{Left, Right};
 use rustc_ast::Mutability;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
-use rustc_middle::mir::interpret::InterpError;
+use rustc_middle::mir::interpret::{
+    ExpectedKind, InterpError, InvalidMetaKind, PointerKind, ValidationErrorInfo,
+    ValidationErrorKind, ValidationErrorKind::*,
+};
 use rustc_middle::ty;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_span::symbol::{sym, Symbol};
@@ -30,14 +33,7 @@ use super::{
 };
 
 macro_rules! throw_validation_failure {
-    ($where:expr, { $( $what_fmt:tt )* } $( expected { $( $expected_fmt:tt )* } )?) => {{
-        let mut msg = String::new();
-        msg.push_str("encountered ");
-        write!(&mut msg, $($what_fmt)*).unwrap();
-        $(
-            msg.push_str(", but expected ");
-            write!(&mut msg, $($expected_fmt)*).unwrap();
-        )?
+    ($where:expr, $kind: expr) => {{
         let where_ = &$where;
         let path = if !where_.is_empty() {
             let mut path = String::new();
@@ -46,7 +42,8 @@ macro_rules! throw_validation_failure {
         } else {
             None
         };
-        throw_ub!(ValidationFailure { path, msg })
+
+        throw_ub!(Validation(ValidationErrorInfo { path, kind: $kind }))
     }};
 }
 
@@ -82,22 +79,22 @@ macro_rules! throw_validation_failure {
 ///
 macro_rules! try_validation {
     ($e:expr, $where:expr,
-    $( $( $p:pat_param )|+ => { $( $what_fmt:tt )* } $( expected { $( $expected_fmt:tt )* } )? ),+ $(,)?
+    $( $( $p:pat_param )|+ => $kind: expr ),+ $(,)?
     ) => {{
         match $e {
             Ok(x) => x,
             // We catch the error and turn it into a validation failure. We are okay with
             // allocation here as this can only slow down builds that fail anyway.
-            Err(e) => match e.kind() {
+            Err(e) => match e.into_parts() {
                 $(
-                    InterpError::UndefinedBehavior($($p)|+) =>
+                    (InterpError::UndefinedBehavior($($p)|+), _) =>
                        throw_validation_failure!(
                             $where,
-                            { $( $what_fmt )* } $( expected { $( $expected_fmt )* } )?
+                            $kind
                         )
                 ),+,
                 #[allow(unreachable_patterns)]
-                _ => Err::<!, _>(e)?,
+                (e, rest) => Err::<!, _>($crate::interpret::InterpErrorInfo::from_parts(e, rest))?,
             }
         }
     }};
@@ -160,6 +157,7 @@ impl<T: Copy + Eq + Hash + std::fmt::Debug, PATH: Default> RefTracking<T, PATH>
     }
 }
 
+// FIXME make this translatable as well?
 /// Format a path
 fn write_path(out: &mut String, path: &[PathElem]) {
     use self::PathElem::*;
@@ -185,26 +183,6 @@ fn write_path(out: &mut String, path: &[PathElem]) {
     }
 }
 
-// Formats such that a sentence like "expected something {}" to mean
-// "expected something <in the given range>" makes sense.
-fn wrapping_range_format(r: WrappingRange, max_hi: u128) -> String {
-    let WrappingRange { start: lo, end: hi } = r;
-    assert!(hi <= max_hi);
-    if lo > hi {
-        format!("less or equal to {}, or greater or equal to {}", hi, lo)
-    } else if lo == hi {
-        format!("equal to {}", lo)
-    } else if lo == 0 {
-        assert!(hi < max_hi, "should not be printing if the range covers everything");
-        format!("less or equal to {}", hi)
-    } else if hi == max_hi {
-        assert!(lo > 0, "should not be printing if the range covers everything");
-        format!("greater or equal to {}", lo)
-    } else {
-        format!("in the range {:?}", r)
-    }
-}
-
 struct ValidityVisitor<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> {
     /// The `path` may be pushed to, but the part that is present when a function
     /// starts must not be changed!  `visit_fields` and `visit_array` rely on
@@ -311,19 +289,19 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
     fn read_immediate(
         &self,
         op: &OpTy<'tcx, M::Provenance>,
-        expected: impl Display,
+        expected: ExpectedKind,
     ) -> InterpResult<'tcx, ImmTy<'tcx, M::Provenance>> {
         Ok(try_validation!(
             self.ecx.read_immediate(op),
             self.path,
-            InvalidUninitBytes(None) => { "uninitialized memory" } expected { "{expected}" }
+            InvalidUninitBytes(None) => Uninit { expected }
         ))
     }
 
     fn read_scalar(
         &self,
         op: &OpTy<'tcx, M::Provenance>,
-        expected: impl Display,
+        expected: ExpectedKind,
     ) -> InterpResult<'tcx, Scalar<M::Provenance>> {
         Ok(self.read_immediate(op, expected)?.to_scalar())
     }
@@ -342,8 +320,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                     self.ecx.get_ptr_vtable(vtable),
                     self.path,
                     DanglingIntPointer(..) |
-                    InvalidVTablePointer(..) =>
-                        { "{vtable}" } expected { "a vtable pointer" },
+                    InvalidVTablePointer(..) => InvalidVTablePtr { value: format!("{vtable}") }
                 );
                 // FIXME: check if the type/trait match what ty::Dynamic says?
             }
@@ -366,10 +343,9 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
     fn check_safe_pointer(
         &mut self,
         value: &OpTy<'tcx, M::Provenance>,
-        kind: &str,
+        ptr_kind: PointerKind,
     ) -> InterpResult<'tcx> {
-        let place =
-            self.ecx.ref_to_mplace(&self.read_immediate(value, format_args!("a {kind}"))?)?;
+        let place = self.ecx.ref_to_mplace(&self.read_immediate(value, ptr_kind.into())?)?;
         // Handle wide pointers.
         // Check metadata early, for better diagnostics
         if place.layout.is_unsized() {
@@ -379,7 +355,10 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
         let size_and_align = try_validation!(
             self.ecx.size_and_align_of_mplace(&place),
             self.path,
-            InvalidMeta(msg) => { "invalid {} metadata: {}", kind, msg },
+            InvalidMeta(msg) => match msg {
+                InvalidMetaKind::SliceTooBig => InvalidMetaSliceTooLarge { ptr_kind },
+                InvalidMetaKind::TooBig => InvalidMetaTooLarge { ptr_kind },
+            }
         );
         let (size, align) = size_and_align
             // for the purpose of validity, consider foreign types to have
@@ -395,31 +374,30 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                 CheckInAllocMsg::InboundsTest, // will anyway be replaced by validity message
             ),
             self.path,
-            AlignmentCheckFailed { required, has } =>
-                {
-                    "an unaligned {kind} (required {} byte alignment but found {})",
-                    required.bytes(),
-                    has.bytes(),
-                },
-            DanglingIntPointer(0, _) =>
-                { "a null {kind}" },
-            DanglingIntPointer(i, _) =>
-                {
-                    "a dangling {kind} ({pointer} has no provenance)",
-                    pointer = Pointer::<Option<AllocId>>::from_addr_invalid(*i),
-                },
-            PointerOutOfBounds { .. } =>
-                { "a dangling {kind} (going beyond the bounds of its allocation)" },
+            AlignmentCheckFailed { required, has } => UnalignedPtr {
+                ptr_kind,
+                required_bytes: required.bytes(),
+                found_bytes: has.bytes()
+            },
+            DanglingIntPointer(0, _) => NullPtr { ptr_kind },
+            DanglingIntPointer(i, _) => DanglingPtrNoProvenance {
+                ptr_kind,
+                // FIXME this says "null pointer" when null but we need translate
+                pointer: format!("{}", Pointer::<Option<AllocId>>::from_addr_invalid(i))
+            },
+            PointerOutOfBounds { .. } => DanglingPtrOutOfBounds {
+                ptr_kind
+            },
             // This cannot happen during const-eval (because interning already detects
             // dangling pointers), but it can happen in Miri.
-            PointerUseAfterFree(..) =>
-                { "a dangling {kind} (use-after-free)" },
+            PointerUseAfterFree(..) => DanglingPtrUseAfterFree {
+                ptr_kind,
+            },
         );
         // Do not allow pointers to uninhabited types.
         if place.layout.abi.is_uninhabited() {
-            throw_validation_failure!(self.path,
-                { "a {kind} pointing to uninhabited type {}", place.layout.ty }
-            )
+            let ty = place.layout.ty;
+            throw_validation_failure!(self.path, PtrToUninhabited { ptr_kind, ty })
         }
         // Recursive checking
         if let Some(ref_tracking) = self.ref_tracking.as_deref_mut() {
@@ -441,9 +419,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                             // this check is so important.
                             // This check is reachable when the const just referenced the static,
                             // but never read it (so we never entered `before_access_global`).
-                            throw_validation_failure!(self.path,
-                                { "a {} pointing to a static variable in a constant", kind }
-                            );
+                            throw_validation_failure!(self.path, PtrToStatic { ptr_kind });
                         }
                         // We skip recursively checking other statics. These statics must be sound by
                         // themselves, and the only way to get broken statics here is by using
@@ -464,9 +440,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                             // This should be unreachable, but if someone manages to copy a pointer
                             // out of a `static`, then that pointer might point to mutable memory,
                             // and we would catch that here.
-                            throw_validation_failure!(self.path,
-                                { "a {} pointing to mutable memory in a constant", kind }
-                            );
+                            throw_validation_failure!(self.path, PtrToMut { ptr_kind });
                         }
                     }
                     // Nothing to check for these.
@@ -496,22 +470,24 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
         let ty = value.layout.ty;
         match ty.kind() {
             ty::Bool => {
-                let value = self.read_scalar(value, "a boolean")?;
+                let value = self.read_scalar(value, ExpectedKind::Bool)?;
                 try_validation!(
                     value.to_bool(),
                     self.path,
-                    InvalidBool(..) =>
-                        { "{:x}", value } expected { "a boolean" },
+                    InvalidBool(..) => ValidationErrorKind::InvalidBool {
+                        value: format!("{value:x}"),
+                    }
                 );
                 Ok(true)
             }
             ty::Char => {
-                let value = self.read_scalar(value, "a unicode scalar value")?;
+                let value = self.read_scalar(value, ExpectedKind::Char)?;
                 try_validation!(
                     value.to_char(),
                     self.path,
-                    InvalidChar(..) =>
-                        { "{:x}", value } expected { "a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)" },
+                    InvalidChar(..) => ValidationErrorKind::InvalidChar {
+                        value: format!("{value:x}"),
+                    }
                 );
                 Ok(true)
             }
@@ -521,16 +497,17 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                 let value = self.read_scalar(
                     value,
                     if matches!(ty.kind(), ty::Float(..)) {
-                        "a floating point number"
+                        ExpectedKind::Float
                     } else {
-                        "an integer"
+                        ExpectedKind::Int
                     },
                 )?;
                 // As a special exception we *do* match on a `Scalar` here, since we truly want
                 // to know its underlying representation (and *not* cast it to an integer).
                 if matches!(value, Scalar::Ptr(..)) {
-                    throw_validation_failure!(self.path,
-                        { "{:x}", value } expected { "plain (non-pointer) bytes" }
+                    throw_validation_failure!(
+                        self.path,
+                        ExpectedNonPtr { value: format!("{value:x}") }
                     )
                 }
                 Ok(true)
@@ -540,7 +517,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                 // actually enforce the strict rules for raw pointers (mostly because
                 // that lets us re-use `ref_to_mplace`).
                 let place =
-                    self.ecx.ref_to_mplace(&self.read_immediate(value, "a raw pointer")?)?;
+                    self.ecx.ref_to_mplace(&self.read_immediate(value, ExpectedKind::RawPtr)?)?;
                 if place.layout.is_unsized() {
                     self.check_wide_ptr_meta(place.meta, place.layout)?;
                 }
@@ -554,14 +531,14 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                     // a ZST).
                     let layout = self.ecx.layout_of(*ty)?;
                     if !layout.is_zst() {
-                        throw_validation_failure!(self.path, { "mutable reference in a `const`" });
+                        throw_validation_failure!(self.path, MutableRefInConst);
                     }
                 }
-                self.check_safe_pointer(value, "reference")?;
+                self.check_safe_pointer(value, PointerKind::Ref)?;
                 Ok(true)
             }
             ty::FnPtr(_sig) => {
-                let value = self.read_scalar(value, "a function pointer")?;
+                let value = self.read_scalar(value, ExpectedKind::FnPtr)?;
 
                 // If we check references recursively, also check that this points to a function.
                 if let Some(_) = self.ref_tracking {
@@ -570,19 +547,20 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                         self.ecx.get_ptr_fn(ptr),
                         self.path,
                         DanglingIntPointer(..) |
-                        InvalidFunctionPointer(..) =>
-                            { "{ptr}" } expected { "a function pointer" },
+                        InvalidFunctionPointer(..) => InvalidFnPtr {
+                            value: format!("{ptr}"),
+                        },
                     );
                     // FIXME: Check if the signature matches
                 } else {
                     // Otherwise (for standalone Miri), we have to still check it to be non-null.
                     if self.ecx.scalar_may_be_null(value)? {
-                        throw_validation_failure!(self.path, { "a null function pointer" });
+                        throw_validation_failure!(self.path, NullFnPtr);
                     }
                 }
                 Ok(true)
             }
-            ty::Never => throw_validation_failure!(self.path, { "a value of the never type `!`" }),
+            ty::Never => throw_validation_failure!(self.path, NeverVal),
             ty::Foreign(..) | ty::FnDef(..) => {
                 // Nothing to check.
                 Ok(true)
@@ -629,12 +607,9 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                 if start == 1 && end == max_value {
                     // Only null is the niche. So make sure the ptr is NOT null.
                     if self.ecx.scalar_may_be_null(scalar)? {
-                        throw_validation_failure!(self.path,
-                            { "a potentially null pointer" }
-                            expected {
-                                "something that cannot possibly fail to be {}",
-                                wrapping_range_format(valid_range, max_value)
-                            }
+                        throw_validation_failure!(
+                            self.path,
+                            NullablePtrOutOfRange { range: valid_range, max_value }
                         )
                     } else {
                         return Ok(());
@@ -645,12 +620,9 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                 } else {
                     // Conservatively, we reject, because the pointer *could* have a bad
                     // value.
-                    throw_validation_failure!(self.path,
-                        { "a pointer" }
-                        expected {
-                            "something that cannot possibly fail to be {}",
-                            wrapping_range_format(valid_range, max_value)
-                        }
+                    throw_validation_failure!(
+                        self.path,
+                        PtrOutOfRange { range: valid_range, max_value }
                     )
                 }
             }
@@ -659,9 +631,9 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
         if valid_range.contains(bits) {
             Ok(())
         } else {
-            throw_validation_failure!(self.path,
-                { "{}", bits }
-                expected { "something {}", wrapping_range_format(valid_range, max_value) }
+            throw_validation_failure!(
+                self.path,
+                OutOfRange { value: format!("{bits}"), range: valid_range, max_value }
             )
         }
     }
@@ -685,10 +657,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
             Ok(try_validation!(
                 this.ecx.read_discriminant(op),
                 this.path,
-                InvalidTag(val) =>
-                    { "{:x}", val } expected { "a valid enum tag" },
-                InvalidUninitBytes(None) =>
-                    { "uninitialized bytes" } expected { "a valid enum tag" },
+                InvalidTag(val) => InvalidEnumTag {
+                    value: format!("{val:x}"),
+                },
+
+                InvalidUninitBytes(None) => UninitEnumTag,
             )
             .1)
         })
@@ -730,7 +703,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
         // Special check preventing `UnsafeCell` inside unions in the inner part of constants.
         if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { inner: true, .. })) {
             if !op.layout.ty.is_freeze(*self.ecx.tcx, self.ecx.param_env) {
-                throw_validation_failure!(self.path, { "`UnsafeCell` in a `const`" });
+                throw_validation_failure!(self.path, UnsafeCell);
             }
         }
         Ok(())
@@ -738,7 +711,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
 
     #[inline]
     fn visit_box(&mut self, op: &OpTy<'tcx, M::Provenance>) -> InterpResult<'tcx> {
-        self.check_safe_pointer(op, "box")?;
+        self.check_safe_pointer(op, PointerKind::Box)?;
         Ok(())
     }
 
@@ -756,7 +729,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
             if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { inner: true, .. }))
                 && def.is_unsafe_cell()
             {
-                throw_validation_failure!(self.path, { "`UnsafeCell` in a `const`" });
+                throw_validation_failure!(self.path, UnsafeCell);
             }
         }
 
@@ -775,14 +748,13 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
         // MyNewtype and then the scalar in there).
         match op.layout.abi {
             Abi::Uninhabited => {
-                throw_validation_failure!(self.path,
-                    { "a value of uninhabited type {:?}", op.layout.ty }
-                );
+                let ty = op.layout.ty;
+                throw_validation_failure!(self.path, UninhabitedVal { ty });
             }
             Abi::Scalar(scalar_layout) => {
                 if !scalar_layout.is_uninit_valid() {
                     // There is something to check here.
-                    let scalar = self.read_scalar(op, "initialized scalar value")?;
+                    let scalar = self.read_scalar(op, ExpectedKind::InitScalar)?;
                     self.visit_scalar(scalar, scalar_layout)?;
                 }
             }
@@ -792,7 +764,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
                 // the other must be init.
                 if !a_layout.is_uninit_valid() && !b_layout.is_uninit_valid() {
                     let (a, b) =
-                        self.read_immediate(op, "initialized scalar value")?.to_scalar_pair();
+                        self.read_immediate(op, ExpectedKind::InitScalar)?.to_scalar_pair();
                     self.visit_scalar(a, a_layout)?;
                     self.visit_scalar(b, b_layout)?;
                 }
@@ -822,7 +794,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
                 try_validation!(
                     self.ecx.read_bytes_ptr_strip_provenance(mplace.ptr, Size::from_bytes(len)),
                     self.path,
-                    InvalidUninitBytes(..) => { "uninitialized data in `str`" },
+                    InvalidUninitBytes(..) => { UninitStr },
                 );
             }
             ty::Array(tys, ..) | ty::Slice(tys)
@@ -852,7 +824,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
                     Left(mplace) => mplace,
                     Right(imm) => match *imm {
                         Immediate::Uninit =>
-                            throw_validation_failure!(self.path, { "uninitialized bytes" }),
+                            throw_validation_failure!(self.path, UninitVal),
                         Immediate::Scalar(..) | Immediate::ScalarPair(..) =>
                             bug!("arrays/slices can never have Scalar/ScalarPair layout"),
                     }
@@ -888,7 +860,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
                                 .unwrap();
                                 self.path.push(PathElem::ArrayElem(i));
 
-                                throw_validation_failure!(self.path, { "uninitialized bytes" })
+                                throw_validation_failure!(self.path, UninitVal)
                             }
 
                             // Propagate upwards (that will also check for unexpected errors).
@@ -929,12 +901,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         match visitor.visit_value(&op) {
             Ok(()) => Ok(()),
             // Pass through validation failures.
-            Err(err) if matches!(err.kind(), err_ub!(ValidationFailure { .. })) => Err(err),
+            Err(err) if matches!(err.kind(), err_ub!(Validation { .. })) => Err(err),
             // Complain about any other kind of UB error -- those are bad because we'd like to
             // report them in a way that shows *where* in the value the issue lies.
             Err(err) if matches!(err.kind(), InterpError::UndefinedBehavior(_)) => {
-                err.print_backtrace();
-                bug!("Unexpected Undefined Behavior error during validation: {}", err);
+                let (err, backtrace) = err.into_parts();
+                backtrace.print_backtrace();
+                bug!("Unexpected Undefined Behavior error during validation: {err:?}");
             }
             // Pass through everything else.
             Err(err) => Err(err),
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index c36282d5ed4..8314f53ba57 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -4,6 +4,7 @@ Rust MIR: a lowered representation of Rust.
 
 */
 
+#![deny(rustc::untranslatable_diagnostic)]
 #![feature(assert_matches)]
 #![feature(box_patterns)]
 #![feature(decl_macro)]
@@ -33,6 +34,8 @@ pub mod interpret;
 pub mod transform;
 pub mod util;
 
+pub use errors::ReportErrorExt;
+
 use rustc_errors::{DiagnosticMessage, SubdiagnosticMessage};
 use rustc_fluent_macro::fluent_messages;
 use rustc_middle::query::Providers;
@@ -56,10 +59,6 @@ pub fn provide(providers: &mut Providers) {
     providers.valtree_to_const_val = |tcx, (ty, valtree)| {
         const_eval::valtree_to_const_value(tcx, ty::ParamEnv::empty().and(ty), valtree)
     };
-    providers.deref_mir_constant = |tcx, param_env_and_value| {
-        let (param_env, value) = param_env_and_value.into_parts();
-        const_eval::deref_mir_constant(tcx, param_env, value)
-    };
     providers.check_validity_requirement = |tcx, (init_kind, param_env_and_ty)| {
         util::check_validity_requirement(tcx, init_kind, param_env_and_ty)
     };
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index 21f3c2c8917..236e43bdfcc 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -2,9 +2,7 @@
 
 use hir::def_id::LocalDefId;
 use hir::{ConstContext, LangItem};
-use rustc_errors::{
-    error_code, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed,
-};
+use rustc_errors::{error_code, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_infer::infer::TyCtxtInferExt;
@@ -152,7 +150,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
 
                     if let Ok(Some(ImplSource::UserDefined(data))) = implsrc {
                         let span = tcx.def_span(data.impl_def_id);
-                        err.span_note(span, "impl defined here, but it is not `const`");
+                        err.subdiagnostic(errors::NonConstImplNote { span });
                     }
                 }
                 _ => {}
@@ -166,26 +164,30 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
         let mut err = match call_kind {
             CallKind::Normal { desugaring: Some((kind, self_ty)), .. } => {
                 macro_rules! error {
-                    ($fmt:literal) => {
-                        struct_span_err!(tcx.sess, span, E0015, $fmt, self_ty, ccx.const_kind())
+                    ($err:ident) => {
+                        tcx.sess.create_err(errors::$err {
+                            span,
+                            ty: self_ty,
+                            kind: ccx.const_kind(),
+                        })
                     };
                 }
 
                 let mut err = match kind {
                     CallDesugaringKind::ForLoopIntoIter => {
-                        error!("cannot convert `{}` into an iterator in {}s")
+                        error!(NonConstForLoopIntoIter)
                     }
                     CallDesugaringKind::QuestionBranch => {
-                        error!("`?` cannot determine the branch of `{}` in {}s")
+                        error!(NonConstQuestionBranch)
                     }
                     CallDesugaringKind::QuestionFromResidual => {
-                        error!("`?` cannot convert from residual of `{}` in {}s")
+                        error!(NonConstQuestionFromResidual)
                     }
                     CallDesugaringKind::TryBlockFromOutput => {
-                        error!("`try` block cannot convert `{}` to the result in {}s")
+                        error!(NonConstTryBlockFromOutput)
                     }
                     CallDesugaringKind::Await => {
-                        error!("cannot convert `{}` into a future in {}s")
+                        error!(NonConstAwait)
                     }
                 };
 
@@ -193,49 +195,31 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                 err
             }
             CallKind::FnCall { fn_trait_id, self_ty } => {
-                let mut err = struct_span_err!(
-                    tcx.sess,
-                    span,
-                    E0015,
-                    "cannot call non-const closure in {}s",
-                    ccx.const_kind(),
-                );
-
-                match self_ty.kind() {
+                let note = match self_ty.kind() {
                     FnDef(def_id, ..) => {
                         let span = tcx.def_span(*def_id);
                         if ccx.tcx.is_const_fn_raw(*def_id) {
                             span_bug!(span, "calling const FnDef errored when it shouldn't");
                         }
 
-                        err.span_note(span, "function defined here, but it is not `const`");
-                    }
-                    FnPtr(..) => {
-                        err.note(format!(
-                            "function pointers need an RFC before allowed to be called in {}s",
-                            ccx.const_kind()
-                        ));
+                        Some(errors::NonConstClosureNote::FnDef { span })
                     }
-                    Closure(..) => {
-                        err.note(format!(
-                            "closures need an RFC before allowed to be called in {}s",
-                            ccx.const_kind()
-                        ));
-                    }
-                    _ => {}
-                }
+                    FnPtr(..) => Some(errors::NonConstClosureNote::FnPtr),
+                    Closure(..) => Some(errors::NonConstClosureNote::Closure),
+                    _ => None,
+                };
+
+                let mut err = tcx.sess.create_err(errors::NonConstClosure {
+                    span,
+                    kind: ccx.const_kind(),
+                    note,
+                });
 
                 diag_trait(&mut err, self_ty, fn_trait_id);
                 err
             }
             CallKind::Operator { trait_id, self_ty, .. } => {
-                let mut err = struct_span_err!(
-                    tcx.sess,
-                    span,
-                    E0015,
-                    "cannot call non-const operator in {}s",
-                    ccx.const_kind()
-                );
+                let mut sugg = None;
 
                 if Some(trait_id) == ccx.tcx.lang_items().eq_trait() {
                     match (substs[0].unpack(), substs[1].unpack()) {
@@ -260,14 +244,11 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                                         let rhs_pos =
                                             span.lo() + BytePos::from_usize(eq_idx + 2 + rhs_idx);
                                         let rhs_span = span.with_lo(rhs_pos).with_hi(rhs_pos);
-                                        err.multipart_suggestion(
-                                            "consider dereferencing here",
-                                            vec![
-                                                (span.shrink_to_lo(), deref.clone()),
-                                                (rhs_span, deref),
-                                            ],
-                                            Applicability::MachineApplicable,
-                                        );
+                                        sugg = Some(errors::ConsiderDereferencing {
+                                            deref,
+                                            span: span.shrink_to_lo(),
+                                            rhs_span,
+                                        });
                                     }
                                 }
                             }
@@ -275,26 +256,29 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
                         _ => {}
                     }
                 }
-
+                let mut err = tcx.sess.create_err(errors::NonConstOperator {
+                    span,
+                    kind: ccx.const_kind(),
+                    sugg,
+                });
                 diag_trait(&mut err, self_ty, trait_id);
                 err
             }
             CallKind::DerefCoercion { deref_target, deref_target_ty, self_ty } => {
-                let mut err = struct_span_err!(
-                    tcx.sess,
-                    span,
-                    E0015,
-                    "cannot perform deref coercion on `{}` in {}s",
-                    self_ty,
-                    ccx.const_kind()
-                );
-
-                err.note(format!("attempting to deref into `{}`", deref_target_ty));
-
                 // Check first whether the source is accessible (issue #87060)
-                if tcx.sess.source_map().is_span_accessible(deref_target) {
-                    err.span_note(deref_target, "deref defined here");
-                }
+                let target = if tcx.sess.source_map().is_span_accessible(deref_target) {
+                    Some(deref_target)
+                } else {
+                    None
+                };
+
+                let mut err = tcx.sess.create_err(errors::NonConstDerefCoercion {
+                    span,
+                    ty: self_ty,
+                    kind: ccx.const_kind(),
+                    target_ty: deref_target_ty,
+                    deref_target: target,
+                });
 
                 diag_trait(&mut err, self_ty, tcx.require_lang_item(LangItem::Deref, Some(span)));
                 err
@@ -432,21 +416,12 @@ impl<'tcx> NonConstOp<'tcx> for LiveDrop<'tcx> {
         ccx: &ConstCx<'_, 'tcx>,
         span: Span,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-        let mut err = struct_span_err!(
-            ccx.tcx.sess,
-            span,
-            E0493,
-            "destructor of `{}` cannot be evaluated at compile-time",
-            self.dropped_ty,
-        );
-        err.span_label(
+        ccx.tcx.sess.create_err(errors::LiveDrop {
             span,
-            format!("the destructor for this type cannot be evaluated in {}s", ccx.const_kind()),
-        );
-        if let Some(span) = self.dropped_at {
-            err.span_label(span, "value is dropped here");
-        }
-        err
+            dropped_ty: self.dropped_ty,
+            kind: ccx.const_kind(),
+            dropped_at: self.dropped_at,
+        })
     }
 }
 
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 23fcd22c52b..29063261ada 100644
--- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
+++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs
@@ -1,6 +1,5 @@
 use rustc_middle::ty::layout::{LayoutCx, LayoutError, LayoutOf, TyAndLayout, ValidityRequirement};
 use rustc_middle::ty::{ParamEnv, ParamEnvAnd, Ty, TyCtxt};
-use rustc_session::Limit;
 use rustc_target::abi::{Abi, FieldsShape, Scalar, Variants};
 
 use crate::const_eval::{CheckAlignment, CompileTimeInterpreter};
@@ -45,11 +44,8 @@ fn might_permit_raw_init_strict<'tcx>(
     tcx: TyCtxt<'tcx>,
     kind: ValidityRequirement,
 ) -> Result<bool, LayoutError<'tcx>> {
-    let machine = CompileTimeInterpreter::new(
-        Limit::new(0),
-        /*can_access_statics:*/ false,
-        CheckAlignment::Error,
-    );
+    let machine =
+        CompileTimeInterpreter::new(/*can_access_statics:*/ false, CheckAlignment::Error);
 
     let mut cx = InterpCx::new(tcx, rustc_span::DUMMY_SP, ParamEnv::reveal_all(), machine);
 
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index 6c3197d8ec2..25a08237346 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -139,9 +139,14 @@ cfg_if! {
 
         impl Atomic<bool> {
             pub fn fetch_or(&self, val: bool, _: Ordering) -> bool {
-                let result = self.0.get() | val;
-                self.0.set(val);
-                result
+                let old = self.0.get();
+                self.0.set(val | old);
+                old
+            }
+            pub fn fetch_and(&self, val: bool, _: Ordering) -> bool {
+                let old = self.0.get();
+                self.0.set(val & old);
+                old
             }
         }
 
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index 2a97c4ff7ae..f3ee83fd4d2 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -492,6 +492,10 @@ impl MultiSpan {
         replacements_occurred
     }
 
+    pub fn pop_span_label(&mut self) -> Option<(Span, DiagnosticMessage)> {
+        self.span_labels.pop()
+    }
+
     /// Returns the strings to highlight. We always ensure that there
     /// is an entry for each of the primary spans -- for each primary
     /// span `P`, if there is at least one label with span `P`, we return
diff --git a/compiler/rustc_errors/messages.ftl b/compiler/rustc_errors/messages.ftl
index 33709734322..8e8223c3cf8 100644
--- a/compiler/rustc_errors/messages.ftl
+++ b/compiler/rustc_errors/messages.ftl
@@ -8,7 +8,11 @@ errors_target_invalid_address_space =
     invalid address space `{$addr_space}` for `{$cause}` in "data-layout": {$err}
 
 errors_target_invalid_alignment =
-    invalid alignment for `{$cause}` in "data-layout": {$err}
+    invalid alignment for `{$cause}` in "data-layout": `{$align}` is {$err_kind ->
+        [not_power_of_two] not a power of 2
+        [too_large] too large
+        *[other] {""}
+    }
 
 errors_target_invalid_bits =
     invalid {$kind} `{$bit}` for `{$cause}` in "data-layout": {$err}
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 488f2d67ee5..ed0d06ed0ff 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -10,7 +10,7 @@ use rustc_lint_defs::{Applicability, LintExpectationId};
 use rustc_span::symbol::Symbol;
 use rustc_span::{Span, DUMMY_SP};
 use std::borrow::Cow;
-use std::fmt;
+use std::fmt::{self, Debug};
 use std::hash::{Hash, Hasher};
 use std::panic::Location;
 
@@ -33,7 +33,7 @@ pub type DiagnosticArgName<'source> = Cow<'source, str>;
 #[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
 pub enum DiagnosticArgValue<'source> {
     Str(Cow<'source, str>),
-    Number(usize),
+    Number(i128),
     StrListSepByAnd(Vec<Cow<'source, str>>),
 }
 
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 65f8a61a30a..10fe7fc74a8 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -60,10 +60,8 @@ into_diagnostic_arg_using_display!(
     u8,
     i16,
     u16,
-    i32,
     u32,
     i64,
-    u64,
     i128,
     u128,
     std::io::Error,
@@ -80,6 +78,18 @@ into_diagnostic_arg_using_display!(
     ExitStatus,
 );
 
+impl IntoDiagnosticArg for i32 {
+    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+        DiagnosticArgValue::Number(self.into())
+    }
+}
+
+impl IntoDiagnosticArg for u64 {
+    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+        DiagnosticArgValue::Number(self.into())
+    }
+}
+
 impl IntoDiagnosticArg for bool {
     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
         if self {
@@ -134,7 +144,7 @@ impl IntoDiagnosticArg for PathBuf {
 
 impl IntoDiagnosticArg for usize {
     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
-        DiagnosticArgValue::Number(self)
+        DiagnosticArgValue::Number(self as i128)
     }
 }
 
@@ -147,9 +157,9 @@ impl IntoDiagnosticArg for PanicStrategy {
 impl IntoDiagnosticArg for hir::ConstContext {
     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
         DiagnosticArgValue::Str(Cow::Borrowed(match self {
-            hir::ConstContext::ConstFn => "constant function",
+            hir::ConstContext::ConstFn => "const_fn",
             hir::ConstContext::Static(_) => "static",
-            hir::ConstContext::Const => "constant",
+            hir::ConstContext::Const => "const",
         }))
     }
 }
@@ -254,7 +264,8 @@ impl IntoDiagnostic<'_, !> for TargetDataLayoutErrors<'_> {
             TargetDataLayoutErrors::InvalidAlignment { cause, err } => {
                 diag = handler.struct_fatal(fluent::errors_target_invalid_alignment);
                 diag.set_arg("cause", cause);
-                diag.set_arg("err", err);
+                diag.set_arg("err_kind", err.diag_ident());
+                diag.set_arg("align", err.align());
                 diag
             }
             TargetDataLayoutErrors::InconsistentTargetArchitecture { dl, target } => {
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 5b2e4d15dfe..0170d52e82a 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -131,7 +131,7 @@ declare_features! (
     /// Allows `crate` in paths.
     (accepted, crate_in_paths, "1.30.0", Some(45477), None),
     /// Allows using `#[debugger_visualizer]` attribute.
-    (accepted, debugger_visualizer, "CURRENT_RUSTC_VERSION", Some(95939), None),
+    (accepted, debugger_visualizer, "1.71.0", Some(95939), None),
     /// Allows rustc to inject a default alloc_error_handler
     (accepted, default_alloc_error_handler, "1.68.0", Some(66741), None),
     /// Allows using assigning a default type to type parameters in algebraic data type definitions.
@@ -281,7 +281,7 @@ declare_features! (
     /// Allows use of the postfix `?` operator in expressions.
     (accepted, question_mark, "1.13.0", Some(31436), None),
     /// Allows the use of raw-dylibs (RFC 2627).
-    (accepted, raw_dylib, "CURRENT_RUSTC_VERSION", Some(58713), None),
+    (accepted, raw_dylib, "1.71.0", Some(58713), None),
     /// Allows keywords to be escaped for use as identifiers.
     (accepted, raw_identifiers, "1.30.0", Some(48589), None),
     /// Allows relaxing the coherence rules such that
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 57e55752027..4c53f9d8369 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -165,7 +165,7 @@ declare_features! (
     /// Allows the `multiple_supertrait_upcastable` lint.
     (active, multiple_supertrait_upcastable, "1.69.0", None, None),
     /// Allow negative trait bounds. This is an internal-only feature for testing the trait solver!
-    (incomplete, negative_bounds, "CURRENT_RUSTC_VERSION", None, None),
+    (incomplete, negative_bounds, "1.71.0", None, None),
     /// Allows using `#[omit_gdb_pretty_printer_section]`.
     (active, omit_gdb_pretty_printer_section, "1.5.0", None, None),
     /// Allows using `#[prelude_import]` on glob `use` items.
@@ -314,15 +314,15 @@ declare_features! (
     /// Allows async functions to be declared, implemented, and used in traits.
     (active, async_fn_in_trait, "1.66.0", Some(91611), None),
     /// Allows builtin # foo() syntax
-    (active, builtin_syntax, "CURRENT_RUSTC_VERSION", Some(110680), None),
+    (active, builtin_syntax, "1.71.0", Some(110680), None),
     /// Allows `c"foo"` literals.
-    (active, c_str_literals, "CURRENT_RUSTC_VERSION", Some(105723), None),
+    (active, c_str_literals, "1.71.0", Some(105723), None),
     /// Treat `extern "C"` function as nounwind.
     (active, c_unwind, "1.52.0", Some(74990), None),
     /// Allows using C-variadics.
     (active, c_variadic, "1.34.0", Some(44930), None),
     /// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour.
-    (active, cfg_overflow_checks, "CURRENT_RUSTC_VERSION", Some(111466), None),
+    (active, cfg_overflow_checks, "1.71.0", Some(111466), None),
     /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
     (active, cfg_sanitize, "1.41.0", Some(39699), None),
     /// Allows `cfg(target_abi = "...")`.
@@ -338,7 +338,7 @@ declare_features! (
     /// Allow conditional compilation depending on rust version
     (active, cfg_version, "1.45.0", Some(64796), None),
     /// Allows to use the `#[cfi_encoding = ""]` attribute.
-    (active, cfi_encoding, "CURRENT_RUSTC_VERSION", Some(89653), None),
+    (active, cfi_encoding, "1.71.0", Some(89653), None),
     /// Allows `for<...>` on closures and generators.
     (active, closure_lifetime_binder, "1.64.0", Some(97362), None),
     /// Allows `#[track_caller]` on closures and generators.
@@ -351,8 +351,6 @@ declare_features! (
     (active, const_async_blocks, "1.53.0", Some(85368), None),
     /// Allows `const || {}` closures in const contexts.
     (incomplete, const_closures, "1.68.0", Some(106003), None),
-    /// Allows limiting the evaluation steps of const expressions
-    (active, const_eval_limit, "1.43.0", Some(67217), None),
     /// Allows the definition of `const extern fn` and `const unsafe extern fn`.
     (active, const_extern_fn, "1.40.0", Some(64926), None),
     /// Allows basic arithmetic on floating point types in a `const fn`.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 06f4a0b5eef..9be28c338f6 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -356,10 +356,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing),
     ungated!(type_length_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing),
     gated!(
-        const_eval_limit, CrateLevel, template!(NameValueStr: "N"), ErrorFollowing,
-        const_eval_limit, experimental!(const_eval_limit)
-    ),
-    gated!(
         move_size_limit, CrateLevel, template!(NameValueStr: "N"), ErrorFollowing,
         large_assignments, experimental!(move_size_limit)
     ),
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 8bca24b2bf0..ed5d76b861a 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -59,8 +59,10 @@ declare_features! (
     /// Allows comparing raw pointers during const eval.
     (removed, const_compare_raw_pointers, "1.46.0", Some(53020), None,
      Some("cannot be allowed in const eval in any meaningful way")),
+    /// Allows limiting the evaluation steps of const expressions
+    (removed, const_eval_limit, "1.43.0", Some(67217), None, Some("removed the limit entirely")),
     /// Allows non-trivial generic constants which have to be manually propagated upwards.
-     (removed, const_evaluatable_checked, "1.48.0", Some(76560), None, Some("renamed to `generic_const_exprs`")),
+    (removed, const_evaluatable_checked, "1.48.0", Some(76560), None, Some("renamed to `generic_const_exprs`")),
     /// Allows the definition of `const` functions with some advanced features.
     (removed, const_fn, "1.54.0", Some(57563), None,
      Some("split into finer-grained feature gates")),
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 3b2c052e8f4..89f96695a2f 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -177,7 +177,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
         }
         // Generic statics are rejected, but we still reach this case.
         Err(e) => {
-            tcx.sess.delay_span_bug(span, e.to_string());
+            tcx.sess.delay_span_bug(span, format!("{e:?}"));
             return;
         }
     };
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
index f7c5b44678f..4d96a7ff4c3 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -1,3 +1,4 @@
+use rustc_errors::StashKey;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem};
@@ -59,7 +60,20 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
         }
     }
 
-    let Some(hidden) = locator.found else {
+    if let Some(hidden) = locator.found {
+        // Only check against typeck if we didn't already error
+        if !hidden.ty.references_error() {
+            for concrete_type in locator.typeck_types {
+                if concrete_type.ty != tcx.erase_regions(hidden.ty)
+                    && !(concrete_type, hidden).references_error()
+                {
+                    hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
+                }
+            }
+        }
+
+        hidden.ty
+    } else {
         let reported = tcx.sess.emit_err(UnconstrainedOpaqueType {
             span: tcx.def_span(def_id),
             name: tcx.item_name(tcx.local_parent(def_id).to_def_id()),
@@ -70,21 +84,8 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
                 _ => "item",
             },
         });
-        return tcx.ty_error(reported);
-    };
-
-    // Only check against typeck if we didn't already error
-    if !hidden.ty.references_error() {
-        for concrete_type in locator.typeck_types {
-            if concrete_type.ty != tcx.erase_regions(hidden.ty)
-                && !(concrete_type, hidden).references_error()
-            {
-                hidden.report_mismatch(&concrete_type, def_id, tcx).emit();
-            }
-        }
+        tcx.ty_error(reported)
     }
-
-    hidden.ty
 }
 
 struct TaitConstraintLocator<'tcx> {
@@ -130,13 +131,28 @@ impl TaitConstraintLocator<'_> {
             self.found = Some(ty::OpaqueHiddenType { span: DUMMY_SP, ty: self.tcx.ty_error(guar) });
             return;
         }
-        let Some(&typeck_hidden_ty) = tables.concrete_opaque_types.get(&self.def_id) else {
+
+        let mut constrained = false;
+        for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
+            if opaque_type_key.def_id != self.def_id {
+                continue;
+            }
+            constrained = true;
+            let concrete_type =
+                self.tcx.erase_regions(hidden_type.remap_generic_params_to_declaration_params(
+                    opaque_type_key,
+                    self.tcx,
+                    true,
+                ));
+            if self.typeck_types.iter().all(|prev| prev.ty != concrete_type.ty) {
+                self.typeck_types.push(concrete_type);
+            }
+        }
+
+        if !constrained {
             debug!("no constraints in typeck results");
             return;
         };
-        if self.typeck_types.iter().all(|prev| prev.ty != typeck_hidden_ty.ty) {
-            self.typeck_types.push(typeck_hidden_ty);
-        }
 
         // Use borrowck to get the type with unerased regions.
         let concrete_opaque_types = &self.tcx.mir_borrowck(item_def_id).concrete_opaque_types;
@@ -190,17 +206,45 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
     }
 }
 
-pub(super) fn find_opaque_ty_constraints_for_rpit(
-    tcx: TyCtxt<'_>,
+pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
+    tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
     owner_def_id: LocalDefId,
 ) -> Ty<'_> {
-    let concrete = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied();
+    let tables = tcx.typeck(owner_def_id);
+
+    // Check that all of the opaques we inferred during HIR are compatible.
+    // FIXME: We explicitly don't check that the types inferred during HIR
+    // typeck are compatible with the one that we infer during borrowck,
+    // because that one actually sometimes has consts evaluated eagerly so
+    // using strict type equality will fail.
+    let mut hir_opaque_ty: Option<ty::OpaqueHiddenType<'tcx>> = None;
+    if tables.tainted_by_errors.is_none() {
+        for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
+            if opaque_type_key.def_id != def_id {
+                continue;
+            }
+            let concrete_type = tcx.erase_regions(
+                hidden_type.remap_generic_params_to_declaration_params(opaque_type_key, tcx, true),
+            );
+            if let Some(prev) = &mut hir_opaque_ty {
+                if concrete_type.ty != prev.ty && !(concrete_type, prev.ty).references_error() {
+                    prev.report_mismatch(&concrete_type, def_id, tcx).stash(
+                        tcx.def_span(opaque_type_key.def_id),
+                        StashKey::OpaqueHiddenTypeMismatch,
+                    );
+                }
+            } else {
+                hir_opaque_ty = Some(concrete_type);
+            }
+        }
+    }
 
-    if let Some(concrete) = concrete {
+    let mir_opaque_ty = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied();
+    if let Some(mir_opaque_ty) = mir_opaque_ty {
         let scope = tcx.hir().local_def_id_to_hir_id(owner_def_id);
         debug!(?scope);
-        let mut locator = RpitConstraintChecker { def_id, tcx, found: concrete };
+        let mut locator = RpitConstraintChecker { def_id, tcx, found: mir_opaque_ty };
 
         match tcx.hir().get(scope) {
             Node::Item(it) => intravisit::walk_item(&mut locator, it),
@@ -208,17 +252,18 @@ pub(super) fn find_opaque_ty_constraints_for_rpit(
             Node::TraitItem(it) => intravisit::walk_trait_item(&mut locator, it),
             other => bug!("{:?} is not a valid scope for an opaque type item", other),
         }
-    }
 
-    concrete.map(|concrete| concrete.ty).unwrap_or_else(|| {
-        let table = tcx.typeck(owner_def_id);
-        if let Some(guar) = table.tainted_by_errors {
-            // Some error in the
-            // owner fn prevented us from populating
+        mir_opaque_ty.ty
+    } else {
+        if let Some(guar) = tables.tainted_by_errors {
+            // Some error in the owner fn prevented us from populating
             // the `concrete_opaque_types` table.
             tcx.ty_error(guar)
         } else {
-            table.concrete_opaque_types.get(&def_id).map(|ty| ty.ty).unwrap_or_else(|| {
+            // Fall back to the RPIT we inferred during HIR typeck
+            if let Some(hir_opaque_ty) = hir_opaque_ty {
+                hir_opaque_ty.ty
+            } else {
                 // We failed to resolve the opaque type or it
                 // resolves to itself. We interpret this as the
                 // no values of the hidden type ever being constructed,
@@ -226,9 +271,9 @@ pub(super) fn find_opaque_ty_constraints_for_rpit(
                 // For backwards compatibility reasons, we fall back to
                 // `()` until we the diverging default is changed.
                 tcx.mk_diverging_default()
-            })
+            }
         }
-    })
+    }
 }
 
 struct RpitConstraintChecker<'tcx> {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index c4add4dbdfb..e19b0664461 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -874,7 +874,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let found = self.resolve_vars_with_obligations(found);
 
         let in_loop = self.is_loop(id)
-            || self.tcx.hir().parent_iter(id).any(|(parent_id, _)| self.is_loop(parent_id));
+            || self
+                .tcx
+                .hir()
+                .parent_iter(id)
+                .take_while(|(_, node)| {
+                    // look at parents until we find the first body owner
+                    node.body_id().is_none()
+                })
+                .any(|(parent_id, _)| self.is_loop(parent_id));
 
         let in_local_statement = self.is_local_statement(id)
             || self
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 0f21fc1e662..964acc4eb77 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -583,19 +583,15 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                 continue;
             }
 
-            let hidden_type =
-                self.tcx().erase_regions(hidden_type.remap_generic_params_to_declaration_params(
-                    opaque_type_key,
-                    self.tcx(),
-                    true,
-                ));
-
+            // Here we only detect impl trait definition conflicts when they
+            // are equal modulo regions.
             if let Some(last_opaque_ty) = self
                 .typeck_results
                 .concrete_opaque_types
-                .insert(opaque_type_key.def_id, hidden_type)
+                .insert(opaque_type_key, hidden_type)
                 && last_opaque_ty.ty != hidden_type.ty
             {
+                assert!(!self.tcx().trait_solver_next());
                 hidden_type
                     .report_mismatch(&last_opaque_ty, opaque_type_key.def_id, self.tcx())
                     .stash(
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index e707ac41a05..98fe3821947 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -155,6 +155,8 @@ lint_builtin_unused_doc_comment = unused doc comment
 lint_builtin_while_true = denote infinite loops with `loop {"{"} ... {"}"}`
     .suggestion = use `loop`
 
+lint_cast_ref_to_mut = casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
+
 lint_check_name_deprecated = lint name `{$lint_name}` is deprecated and does not have an effect anymore. Use: {$new_name}
 
 lint_check_name_unknown = unknown lint: `{$lint_name}`
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 358d412a4d8..213e8db66a0 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -1317,10 +1317,14 @@ declare_lint! {
     ///
     /// ### Explanation
     ///
-    /// A bare `pub` visibility may be misleading if the item is not actually
-    /// publicly exported from the crate. The `pub(crate)` visibility is
-    /// recommended to be used instead, which more clearly expresses the intent
-    /// that the item is only visible within its own crate.
+    /// The `pub` keyword both expresses an intent for an item to be publicly available, and also
+    /// signals to the compiler to make the item publicly accessible. The intent can only be
+    /// satisfied, however, if all items which contain this item are *also* publicly accessible.
+    /// Thus, this lint serves to identify situations where the intent does not match the reality.
+    ///
+    /// If you wish the item to be accessible elsewhere within the crate, but not outside it, the
+    /// `pub(crate)` visibility is recommended to be used instead. This more clearly expresses the
+    /// intent that the item is only visible within its own crate.
     ///
     /// This lint is "allow" by default because it will trigger for a large
     /// amount existing Rust code, and has some false-positives. Eventually it
diff --git a/compiler/rustc_lint/src/cast_ref_to_mut.rs b/compiler/rustc_lint/src/cast_ref_to_mut.rs
new file mode 100644
index 00000000000..84308d48c10
--- /dev/null
+++ b/compiler/rustc_lint/src/cast_ref_to_mut.rs
@@ -0,0 +1,72 @@
+use rustc_ast::Mutability;
+use rustc_hir::{Expr, ExprKind, MutTy, TyKind, UnOp};
+use rustc_middle::ty;
+use rustc_span::sym;
+
+use crate::{lints::CastRefToMutDiag, LateContext, LateLintPass, LintContext};
+
+declare_lint! {
+    /// The `cast_ref_to_mut` lint checks for casts of `&T` to `&mut T`
+    /// without using interior mutability.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// fn x(r: &i32) {
+    ///     unsafe {
+    ///         *(r as *const i32 as *mut i32) += 1;
+    ///     }
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Casting `&T` to `&mut T` without using interior mutability is undefined behavior,
+    /// as it's a violation of Rust reference aliasing requirements.
+    ///
+    /// `UnsafeCell` is the only way to obtain aliasable data that is considered
+    /// mutable.
+    CAST_REF_TO_MUT,
+    Deny,
+    "casts of `&T` to `&mut T` without interior mutability"
+}
+
+declare_lint_pass!(CastRefToMut => [CAST_REF_TO_MUT]);
+
+impl<'tcx> LateLintPass<'tcx> for CastRefToMut {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
+        let ExprKind::Unary(UnOp::Deref, e) = &expr.kind else { return; };
+
+        let e = e.peel_blocks();
+        let e = if let ExprKind::Cast(e, t) = e.kind
+            && let TyKind::Ptr(MutTy { mutbl: Mutability::Mut, .. }) = t.kind {
+            e
+        } else if let ExprKind::MethodCall(_, expr, [], _) = e.kind
+            && let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
+            && cx.tcx.is_diagnostic_item(sym::ptr_cast_mut, def_id) {
+            expr
+        } else {
+            return;
+        };
+
+        let e = e.peel_blocks();
+        let e = if let ExprKind::Cast(e, t) = e.kind
+            && let TyKind::Ptr(MutTy { mutbl: Mutability::Not, .. }) = t.kind {
+            e
+        } else if let ExprKind::Call(path, [arg]) = e.kind
+            && let ExprKind::Path(ref qpath) = path.kind
+            && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
+            && cx.tcx.is_diagnostic_item(sym::ptr_from_ref, def_id) {
+            arg
+        } else {
+            return;
+        };
+
+        let e = e.peel_blocks();
+        if let ty::Ref(..) = cx.typeck_results().node_type(e.hir_id).kind() {
+            cx.emit_spanned_lint(CAST_REF_TO_MUT, expr.span, CastRefToMutDiag);
+        }
+    }
+}
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index c62109b2986..5e3f057d428 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -50,6 +50,7 @@ extern crate tracing;
 
 mod array_into_iter;
 pub mod builtin;
+mod cast_ref_to_mut;
 mod context;
 mod deref_into_dyn_supertrait;
 mod drop_forget_useless;
@@ -97,6 +98,7 @@ use rustc_span::Span;
 
 use array_into_iter::ArrayIntoIter;
 use builtin::*;
+use cast_ref_to_mut::*;
 use deref_into_dyn_supertrait::*;
 use drop_forget_useless::*;
 use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
@@ -214,6 +216,7 @@ late_lint_methods!(
             BoxPointers: BoxPointers,
             PathStatements: PathStatements,
             LetUnderscore: LetUnderscore,
+            CastRefToMut: CastRefToMut,
             // Depends on referenced function signatures in expressions
             UnusedResults: UnusedResults,
             NonUpperCaseGlobals: NonUpperCaseGlobals,
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 746abebeb37..fd15f795202 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -718,6 +718,11 @@ pub enum InvalidFromUtf8Diag {
     },
 }
 
+// cast_ref_to_mut.rs
+#[derive(LintDiagnostic)]
+#[diag(lint_cast_ref_to_mut)]
+pub struct CastRefToMutDiag;
+
 // hidden_unicode_codepoints.rs
 #[derive(LintDiagnostic)]
 #[diag(lint_hidden_unicode_codepoints)]
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 1507087bdd4..eb246c3f93e 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -3357,6 +3357,7 @@ declare_lint_pass! {
         LARGE_ASSIGNMENTS,
         LATE_BOUND_LIFETIME_ARGUMENTS,
         LEGACY_DERIVE_HELPERS,
+        LONG_RUNNING_CONST_EVAL,
         LOSSY_PROVENANCE_CASTS,
         MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
         MACRO_USE_EXTERN_CRATE,
@@ -3427,6 +3428,43 @@ declare_lint_pass! {
 }
 
 declare_lint! {
+    /// The `long_running_const_eval` lint is emitted when const
+    /// eval is running for a long time to ensure rustc terminates
+    /// even if you accidentally wrote an infinite loop.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// const FOO: () = loop {};
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Loops allow const evaluation to compute arbitrary code, but may also
+    /// cause infinite loops or just very long running computations.
+    /// Users can enable long running computations by allowing the lint
+    /// on individual constants or for entire crates.
+    ///
+    /// ### Unconditional warnings
+    ///
+    /// Note that regardless of whether the lint is allowed or set to warn,
+    /// the compiler will issue warnings if constant evaluation runs significantly
+    /// longer than this lint's limit. These warnings are also shown to downstream
+    /// users from crates.io or similar registries. If you are above the lint's limit,
+    /// both you and downstream users might be exposed to these warnings.
+    /// They might also appear on compiler updates, as the compiler makes minor changes
+    /// about how complexity is measured: staying below the limit ensures that there
+    /// is enough room, and given that the lint is disabled for people who use your
+    /// dependency it means you will be the only one to get the warning and can put
+    /// out an update in your own time.
+    pub LONG_RUNNING_CONST_EVAL,
+    Deny,
+    "detects long const eval operations"
+}
+
+declare_lint! {
     /// The `unused_doc_comments` lint detects doc comments that aren't used
     /// by `rustdoc`.
     ///
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
index cd6e3687460..2e6e84ad80e 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
@@ -14,6 +14,8 @@ use syn::Token;
 use syn::{parse_quote, spanned::Spanned, Attribute, Meta, Path, Type};
 use synstructure::{BindingInfo, Structure, VariantInfo};
 
+use super::utils::SubdiagnosticVariant;
+
 /// What kind of diagnostic is being derived - a fatal/error/warning or a lint?
 #[derive(Clone, PartialEq, Eq)]
 pub(crate) enum DiagnosticDeriveKind {
@@ -150,19 +152,19 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
     fn parse_subdiag_attribute(
         &self,
         attr: &Attribute,
-    ) -> Result<Option<(SubdiagnosticKind, Path)>, DiagnosticDeriveError> {
-        let Some((subdiag, slug)) = SubdiagnosticKind::from_attr(attr, self)? else {
+    ) -> Result<Option<(SubdiagnosticKind, Path, bool)>, DiagnosticDeriveError> {
+        let Some(subdiag) = SubdiagnosticVariant::from_attr(attr, self)? else {
             // Some attributes aren't errors - like documentation comments - but also aren't
             // subdiagnostics.
             return Ok(None);
         };
 
-        if let SubdiagnosticKind::MultipartSuggestion { .. } = subdiag {
+        if let SubdiagnosticKind::MultipartSuggestion { .. } = subdiag.kind {
             throw_invalid_attr!(attr, |diag| diag
                 .help("consider creating a `Subdiagnostic` instead"));
         }
 
-        let slug = slug.unwrap_or_else(|| match subdiag {
+        let slug = subdiag.slug.unwrap_or_else(|| match subdiag.kind {
             SubdiagnosticKind::Label => parse_quote! { _subdiag::label },
             SubdiagnosticKind::Note => parse_quote! { _subdiag::note },
             SubdiagnosticKind::Help => parse_quote! { _subdiag::help },
@@ -171,7 +173,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
             SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(),
         });
 
-        Ok(Some((subdiag, slug)))
+        Ok(Some((subdiag.kind, slug, subdiag.no_span)))
     }
 
     /// Establishes state in the `DiagnosticDeriveBuilder` resulting from the struct
@@ -229,7 +231,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
             return Ok(tokens);
         }
 
-        let Some((subdiag, slug)) = self.parse_subdiag_attribute(attr)? else {
+        let Some((subdiag, slug, _no_span)) = self.parse_subdiag_attribute(attr)? else {
             // Some attributes aren't errors - like documentation comments - but also aren't
             // subdiagnostics.
             return Ok(quote! {});
@@ -380,7 +382,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
             _ => (),
         }
 
-        let Some((subdiag, slug)) = self.parse_subdiag_attribute(attr)? else {
+        let Some((subdiag, slug, _no_span)) = self.parse_subdiag_attribute(attr)? else {
             // Some attributes aren't errors - like documentation comments - but also aren't
             // subdiagnostics.
             return Ok(quote! {});
diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
index 374ba1a45c0..e3d9eb96574 100644
--- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
@@ -14,6 +14,8 @@ use quote::{format_ident, quote};
 use syn::{spanned::Spanned, Attribute, Meta, MetaList, Path};
 use synstructure::{BindingInfo, Structure, VariantInfo};
 
+use super::utils::SubdiagnosticVariant;
+
 /// The central struct for constructing the `add_to_diagnostic` method from an annotated struct.
 pub(crate) struct SubdiagnosticDeriveBuilder {
     diag: syn::Ident,
@@ -180,11 +182,13 @@ impl<'a> FromIterator<&'a SubdiagnosticKind> for KindsStatistics {
 }
 
 impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
-    fn identify_kind(&mut self) -> Result<Vec<(SubdiagnosticKind, Path)>, DiagnosticDeriveError> {
+    fn identify_kind(
+        &mut self,
+    ) -> Result<Vec<(SubdiagnosticKind, Path, bool)>, DiagnosticDeriveError> {
         let mut kind_slugs = vec![];
 
         for attr in self.variant.ast().attrs {
-            let Some((kind, slug)) = SubdiagnosticKind::from_attr(attr, self)? else {
+            let Some(SubdiagnosticVariant { kind, slug, no_span }) = SubdiagnosticVariant::from_attr(attr, self)? else {
                 // Some attributes aren't errors - like documentation comments - but also aren't
                 // subdiagnostics.
                 continue;
@@ -202,7 +206,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
                 );
             };
 
-            kind_slugs.push((kind, slug));
+            kind_slugs.push((kind, slug, no_span));
         }
 
         Ok(kind_slugs)
@@ -487,7 +491,8 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
             }
         };
 
-        let kind_stats: KindsStatistics = kind_slugs.iter().map(|(kind, _slug)| kind).collect();
+        let kind_stats: KindsStatistics =
+            kind_slugs.iter().map(|(kind, _slug, _no_span)| kind).collect();
 
         let init = if kind_stats.has_multipart_suggestion {
             quote! { let mut suggestions = Vec::new(); }
@@ -508,13 +513,17 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
         let diag = &self.parent.diag;
         let f = &self.parent.f;
         let mut calls = TokenStream::new();
-        for (kind, slug) in kind_slugs {
+        for (kind, slug, no_span) in kind_slugs {
             let message = format_ident!("__message");
             calls.extend(
                 quote! { let #message = #f(#diag, crate::fluent_generated::#slug.into()); },
             );
 
-            let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind);
+            let name = format_ident!(
+                "{}{}",
+                if span_field.is_some() && !no_span { "span_" } else { "" },
+                kind
+            );
             let call = match kind {
                 SubdiagnosticKind::Suggestion {
                     suggestion_kind,
@@ -566,7 +575,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
                     }
                 }
                 _ => {
-                    if let Some(span) = span_field {
+                    if let Some(span) = span_field && !no_span {
                         quote! { #diag.#name(#span, #message); }
                     } else {
                         quote! { #diag.#name(#message); }
diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs
index e2434981f8d..85dd9f6a3ce 100644
--- a/compiler/rustc_macros/src/diagnostics/utils.rs
+++ b/compiler/rustc_macros/src/diagnostics/utils.rs
@@ -597,14 +597,20 @@ pub(super) enum SubdiagnosticKind {
     },
 }
 
-impl SubdiagnosticKind {
-    /// Constructs a `SubdiagnosticKind` from a field or type attribute such as `#[note]`,
-    /// `#[error(parser::add_paren)]` or `#[suggestion(code = "...")]`. Returns the
+pub(super) struct SubdiagnosticVariant {
+    pub(super) kind: SubdiagnosticKind,
+    pub(super) slug: Option<Path>,
+    pub(super) no_span: bool,
+}
+
+impl SubdiagnosticVariant {
+    /// Constructs a `SubdiagnosticVariant` from a field or type attribute such as `#[note]`,
+    /// `#[error(parser::add_paren, no_span)]` or `#[suggestion(code = "...")]`. Returns the
     /// `SubdiagnosticKind` and the diagnostic slug, if specified.
     pub(super) fn from_attr(
         attr: &Attribute,
         fields: &impl HasFieldMap,
-    ) -> Result<Option<(SubdiagnosticKind, Option<Path>)>, DiagnosticDeriveError> {
+    ) -> Result<Option<SubdiagnosticVariant>, DiagnosticDeriveError> {
         // Always allow documentation comments.
         if is_doc_comment(attr) {
             return Ok(None);
@@ -679,7 +685,7 @@ impl SubdiagnosticKind {
                     | SubdiagnosticKind::Help
                     | SubdiagnosticKind::Warn
                     | SubdiagnosticKind::MultipartSuggestion { .. } => {
-                        return Ok(Some((kind, None)));
+                        return Ok(Some(SubdiagnosticVariant { kind, slug: None, no_span: false }));
                     }
                     SubdiagnosticKind::Suggestion { .. } => {
                         throw_span_err!(span, "suggestion without `code = \"...\"`")
@@ -696,11 +702,14 @@ impl SubdiagnosticKind {
 
         let mut first = true;
         let mut slug = None;
+        let mut no_span = false;
 
         list.parse_nested_meta(|nested| {
             if nested.input.is_empty() || nested.input.peek(Token![,]) {
                 if first {
                     slug = Some(nested.path);
+                } else if nested.path.is_ident("no_span") {
+                    no_span = true;
                 } else {
                     span_err(nested.input.span().unwrap(), "a diagnostic slug must be the first argument to the attribute").emit();
                 }
@@ -775,19 +784,19 @@ impl SubdiagnosticKind {
                 (_, SubdiagnosticKind::Suggestion { .. }) => {
                     span_err(path_span, "invalid nested attribute")
                         .help(
-                            "only `style`, `code` and `applicability` are valid nested attributes",
+                            "only `no_span`, `style`, `code` and `applicability` are valid nested attributes",
                         )
                         .emit();
                     has_errors = true;
                 }
                 (_, SubdiagnosticKind::MultipartSuggestion { .. }) => {
                     span_err(path_span, "invalid nested attribute")
-                        .help("only `style` and `applicability` are valid nested attributes")
+                        .help("only `no_span`, `style` and `applicability` are valid nested attributes")
                         .emit();
                     has_errors = true;
                 }
                 _ => {
-                    span_err(path_span, "invalid nested attribute").emit();
+                    span_err(path_span, "only `no_span` is a valid nested attribute").emit();
                     has_errors = true;
                 }
             }
@@ -831,7 +840,7 @@ impl SubdiagnosticKind {
             | SubdiagnosticKind::Warn => {}
         }
 
-        Ok(Some((kind, slug)))
+        Ok(Some(SubdiagnosticVariant { kind, slug, no_span }))
     }
 }
 
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index aaf72ab94e7..b3976d756eb 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -365,6 +365,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
         lib: Library,
         dep_kind: CrateDepKind,
         name: Symbol,
+        private_dep: Option<bool>,
     ) -> Result<CrateNum, CrateError> {
         let _prof_timer = self.sess.prof.generic_activity("metadata_register_crate");
 
@@ -372,8 +373,13 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
         let crate_root = metadata.get_root();
         let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash());
 
-        let private_dep =
-            self.sess.opts.externs.get(name.as_str()).is_some_and(|e| e.is_private_dep);
+        let private_dep = self
+            .sess
+            .opts
+            .externs
+            .get(name.as_str())
+            .map_or(private_dep.unwrap_or(false), |e| e.is_private_dep)
+            && private_dep.unwrap_or(true);
 
         // Claim this crate number and cache it
         let cnum = self.cstore.intern_stable_crate_id(&crate_root)?;
@@ -518,15 +524,16 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
         if !name.as_str().is_ascii() {
             return Err(CrateError::NonAsciiName(name));
         }
-        let (root, hash, host_hash, extra_filename, path_kind) = match dep {
+        let (root, hash, host_hash, extra_filename, path_kind, private_dep) = match dep {
             Some((root, dep)) => (
                 Some(root),
                 Some(dep.hash),
                 dep.host_hash,
                 Some(&dep.extra_filename[..]),
                 PathKind::Dependency,
+                Some(dep.is_private),
             ),
-            None => (None, None, None, None, PathKind::Crate),
+            None => (None, None, None, None, PathKind::Crate, None),
         };
         let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) {
             (LoadResult::Previous(cnum), None)
@@ -562,10 +569,13 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
                     dep_kind = CrateDepKind::MacrosOnly;
                 }
                 data.update_dep_kind(|data_dep_kind| cmp::max(data_dep_kind, dep_kind));
+                if let Some(private_dep) = private_dep {
+                    data.update_and_private_dep(private_dep);
+                }
                 Ok(cnum)
             }
             (LoadResult::Loaded(library), host_library) => {
-                self.register_crate(host_library, root, library, dep_kind, name)
+                self.register_crate(host_library, root, library, dep_kind, name, private_dep)
             }
             _ => panic!(),
         }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 09e24e012af..8f883bdcf12 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -9,7 +9,7 @@ use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::owned_slice::OwnedSlice;
 use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc, OnceCell};
+use rustc_data_structures::sync::{AppendOnlyVec, AtomicBool, Lock, Lrc, OnceCell};
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
 use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, DeriveProcMacro};
@@ -40,6 +40,7 @@ use proc_macro::bridge::client::ProcMacro;
 use std::iter::TrustedLen;
 use std::num::NonZeroUsize;
 use std::path::Path;
+use std::sync::atomic::Ordering;
 use std::{io, iter, mem};
 
 pub(super) use cstore_impl::provide;
@@ -112,9 +113,10 @@ pub(crate) struct CrateMetadata {
     dep_kind: Lock<CrateDepKind>,
     /// Filesystem location of this crate.
     source: Lrc<CrateSource>,
-    /// Whether or not this crate should be consider a private dependency
-    /// for purposes of the 'exported_private_dependencies' lint
-    private_dep: bool,
+    /// Whether or not this crate should be consider a private dependency.
+    /// Used by the 'exported_private_dependencies' lint, and for determining
+    /// whether to emit suggestions that reference this crate.
+    private_dep: AtomicBool,
     /// The hash for the host proc macro. Used to support `-Z dual-proc-macro`.
     host_hash: Option<Svh>,
 
@@ -701,12 +703,13 @@ impl MetadataBlob {
         writeln!(out, "=External Dependencies=")?;
 
         for (i, dep) in root.crate_deps.decode(self).enumerate() {
-            let CrateDep { name, extra_filename, hash, host_hash, kind } = dep;
+            let CrateDep { name, extra_filename, hash, host_hash, kind, is_private } = dep;
             let number = i + 1;
 
             writeln!(
                 out,
-                "{number} {name}{extra_filename} hash {hash} host_hash {host_hash:?} kind {kind:?}"
+                "{number} {name}{extra_filename} hash {hash} host_hash {host_hash:?} kind {kind:?} {privacy}",
+                privacy = if is_private { "private" } else { "public" }
             )?;
         }
         write!(out, "\n")?;
@@ -1624,7 +1627,7 @@ impl CrateMetadata {
             dependencies,
             dep_kind: Lock::new(dep_kind),
             source: Lrc::new(source),
-            private_dep,
+            private_dep: AtomicBool::new(private_dep),
             host_hash,
             extern_crate: Lock::new(None),
             hygiene_context: Default::default(),
@@ -1672,6 +1675,10 @@ impl CrateMetadata {
         self.dep_kind.with_lock(|dep_kind| *dep_kind = f(*dep_kind))
     }
 
+    pub(crate) fn update_and_private_dep(&self, private_dep: bool) {
+        self.private_dep.fetch_and(private_dep, Ordering::SeqCst);
+    }
+
     pub(crate) fn required_panic_strategy(&self) -> Option<PanicStrategy> {
         self.root.required_panic_strategy
     }
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 3d8991d99b5..a15307e4345 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -285,7 +285,13 @@ provide! { tcx, def_id, other, cdata,
     is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) }
 
     dylib_dependency_formats => { cdata.get_dylib_dependency_formats(tcx) }
-    is_private_dep => { cdata.private_dep }
+    is_private_dep => {
+        // Parallel compiler needs to synchronize type checking and linting (which use this flag)
+        // so that they happen strictly crate loading. Otherwise, the full list of available
+        // impls aren't loaded yet.
+        use std::sync::atomic::Ordering;
+        cdata.private_dep.load(Ordering::Acquire)
+    }
     is_panic_runtime => { cdata.root.panic_runtime }
     is_compiler_builtins => { cdata.root.compiler_builtins }
     has_global_allocator => { cdata.root.has_global_allocator }
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index c673eb5afc7..6ceb61e793e 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1883,6 +1883,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                     host_hash: self.tcx.crate_host_hash(cnum),
                     kind: self.tcx.dep_kind(cnum),
                     extra_filename: self.tcx.extra_filename(cnum).clone(),
+                    is_private: self.tcx.is_private_dep(cnum),
                 };
                 (cnum, dep)
             })
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index ce2fe70a8b2..2da888f4468 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -322,6 +322,7 @@ pub(crate) struct CrateDep {
     pub host_hash: Option<Svh>,
     pub kind: CrateDepKind,
     pub extra_filename: String,
+    pub is_private: bool,
 }
 
 #[derive(MetadataEncodable, MetadataDecodable)]
diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs
index dda30bce2c0..f002d7f97b9 100644
--- a/compiler/rustc_metadata/src/rmeta/table.rs
+++ b/compiler/rustc_metadata/src/rmeta/table.rs
@@ -439,7 +439,7 @@ where
     /// Given the metadata, extract out the value at a particular index (if any).
     #[inline(never)]
     pub(super) fn get<'a, 'tcx, M: Metadata<'a, 'tcx>>(&self, metadata: M, i: I) -> T::Value<'tcx> {
-        debug!("LazyTable::lookup: index={:?} len={:?}", i, self.encoded_size);
+        trace!("LazyTable::lookup: index={:?} len={:?}", i, self.encoded_size);
 
         let start = self.position.get();
         let bytes = &metadata.blob()[start..start + self.encoded_size];
diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl
index 3d581daa925..bb7147ac80f 100644
--- a/compiler/rustc_middle/messages.ftl
+++ b/compiler/rustc_middle/messages.ftl
@@ -1,3 +1,38 @@
+middle_adjust_for_foreign_abi_error =
+    target architecture {$arch} does not support `extern {$abi}` ABI
+
+middle_assert_async_resume_after_panic = `async fn` resumed after panicking
+
+middle_assert_async_resume_after_return = `async fn` resumed after completion
+
+middle_assert_divide_by_zero =
+    attempt to divide `{$val}` by zero
+
+middle_assert_generator_resume_after_panic = generator resumed after panicking
+
+middle_assert_generator_resume_after_return = generator resumed after completion
+
+middle_assert_misaligned_ptr_deref =
+    misaligned pointer dereference: address must be a multiple of {$required} but is {$found}
+
+middle_assert_op_overflow =
+    attempt to compute `{$left} {$op} {$right}`, which would overflow
+
+middle_assert_overflow_neg =
+    attempt to negate `{$val}`, which would overflow
+
+middle_assert_remainder_by_zero =
+    attempt to calculate the remainder of `{$val}` with a divisor of zero
+
+middle_assert_shl_overflow =
+    attempt to shift left by `{$val}`, which would overflow
+
+middle_assert_shr_overflow =
+    attempt to shift right by `{$val}`, which would overflow
+
+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
 
diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/error.rs
index 046186d274c..57b2de84b47 100644
--- a/compiler/rustc_middle/src/error.rs
+++ b/compiler/rustc_middle/src/error.rs
@@ -1,3 +1,7 @@
+use std::borrow::Cow;
+use std::fmt;
+
+use rustc_errors::{DiagnosticArgValue, DiagnosticMessage};
 use rustc_macros::Diagnostic;
 use rustc_span::{Span, Symbol};
 
@@ -88,3 +92,54 @@ pub(super) struct ConstNotUsedTraitAlias {
     #[primary_span]
     pub span: Span,
 }
+
+pub struct CustomSubdiagnostic<'a> {
+    pub msg: fn() -> DiagnosticMessage,
+    pub add_args:
+        Box<dyn FnOnce(&mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue<'static>)) + 'a>,
+}
+
+impl<'a> CustomSubdiagnostic<'a> {
+    pub fn label(x: fn() -> DiagnosticMessage) -> Self {
+        Self::label_and_then(x, |_| {})
+    }
+    pub fn label_and_then<
+        F: FnOnce(&mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue<'static>)) + 'a,
+    >(
+        msg: fn() -> DiagnosticMessage,
+        f: F,
+    ) -> Self {
+        Self { msg, add_args: Box::new(move |x| f(x)) }
+    }
+}
+
+impl fmt::Debug for CustomSubdiagnostic<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("CustomSubdiagnostic").finish_non_exhaustive()
+    }
+}
+
+#[derive(Diagnostic)]
+pub enum LayoutError<'tcx> {
+    #[diag(middle_unknown_layout)]
+    Unknown { ty: Ty<'tcx> },
+
+    #[diag(middle_values_too_big)]
+    Overflow { ty: Ty<'tcx> },
+
+    #[diag(middle_cannot_be_normalized)]
+    NormalizationFailure { ty: Ty<'tcx>, failure_ty: String },
+
+    #[diag(middle_cycle)]
+    Cycle,
+}
+
+#[derive(Diagnostic)]
+#[diag(middle_adjust_for_foreign_abi_error)]
+pub struct UnsupportedFnAbi {
+    pub arch: Symbol,
+    pub abi: &'static str,
+}
+
+/// Used by `rustc_const_eval`
+pub use crate::fluent_generated::middle_adjust_for_foreign_abi_error;
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 22ee2a8c5e5..0d6c2eba06c 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -48,6 +48,7 @@
 #![feature(associated_type_bounds)]
 #![feature(rustc_attrs)]
 #![feature(control_flow_enum)]
+#![feature(trait_upcasting)]
 #![feature(trusted_step)]
 #![feature(try_blocks)]
 #![feature(try_reserve_kind)]
@@ -86,7 +87,7 @@ mod macros;
 
 #[macro_use]
 pub mod arena;
-pub(crate) mod error;
+pub mod error;
 pub mod hir;
 pub mod infer;
 pub mod lint;
diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs
index bd859d4d61b..d4f023958d6 100644
--- a/compiler/rustc_middle/src/middle/limits.rs
+++ b/compiler/rustc_middle/src/middle/limits.rs
@@ -1,8 +1,7 @@
 //! Registering limits:
 //! * recursion_limit,
-//! * move_size_limit,
-//! * type_length_limit, and
-//! * const_eval_limit
+//! * move_size_limit, and
+//! * type_length_limit
 //!
 //! There are various parts of the compiler that must impose arbitrary limits
 //! on how deeply they recurse to prevent stack overflow. Users can override
@@ -34,12 +33,6 @@ pub fn provide(providers: &mut Providers) {
             sym::type_length_limit,
             1048576,
         ),
-        const_eval_limit: get_limit(
-            tcx.hir().krate_attrs(),
-            tcx.sess,
-            sym::const_eval_limit,
-            2_000_000,
-        ),
     }
 }
 
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 1a8e4826447..b8030d9db13 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -296,25 +296,13 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
         Allocation::from_bytes(slice, Align::ONE, Mutability::Not)
     }
 
-    /// Try to create an Allocation of `size` bytes, failing if there is not enough memory
-    /// available to the compiler to do so.
-    ///
-    /// If `panic_on_fail` is true, this will never return `Err`.
-    pub fn uninit<'tcx>(size: Size, align: Align, panic_on_fail: bool) -> InterpResult<'tcx, Self> {
-        let bytes = Bytes::zeroed(size, align).ok_or_else(|| {
-            // This results in an error that can happen non-deterministically, since the memory
-            // available to the compiler can change between runs. Normally queries are always
-            // deterministic. However, we can be non-deterministic here because all uses of const
-            // evaluation (including ConstProp!) will make compilation fail (via hard error
-            // or ICE) upon encountering a `MemoryExhausted` error.
-            if panic_on_fail {
-                panic!("Allocation::uninit called with panic_on_fail had allocation failure")
-            }
-            ty::tls::with(|tcx| {
-                tcx.sess.delay_span_bug(DUMMY_SP, "exhausted memory during interpretation")
-            });
-            InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
-        })?;
+    fn uninit_inner<R>(size: Size, align: Align, fail: impl FnOnce() -> R) -> Result<Self, R> {
+        // This results in an error that can happen non-deterministically, since the memory
+        // available to the compiler can change between runs. Normally queries are always
+        // deterministic. However, we can be non-deterministic here because all uses of const
+        // evaluation (including ConstProp!) will make compilation fail (via hard error
+        // or ICE) upon encountering a `MemoryExhausted` error.
+        let bytes = Bytes::zeroed(size, align).ok_or_else(fail)?;
 
         Ok(Allocation {
             bytes,
@@ -325,6 +313,28 @@ impl<Prov: Provenance, Bytes: AllocBytes> Allocation<Prov, (), Bytes> {
             extra: (),
         })
     }
+
+    /// Try to create an Allocation of `size` bytes, failing if there is not enough memory
+    /// available to the compiler to do so.
+    pub fn try_uninit<'tcx>(size: Size, align: Align) -> InterpResult<'tcx, Self> {
+        Self::uninit_inner(size, align, || {
+            ty::tls::with(|tcx| {
+                tcx.sess.delay_span_bug(DUMMY_SP, "exhausted memory during interpretation")
+            });
+            InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted).into()
+        })
+    }
+
+    /// Try to create an Allocation of `size` bytes, panics if there is not enough memory
+    /// available to the compiler to do so.
+    pub fn uninit(size: Size, align: Align) -> Self {
+        match Self::uninit_inner(size, align, || {
+            panic!("Allocation::uninit called with panic_on_fail had allocation failure");
+        }) {
+            Ok(x) => x,
+            Err(x) => x,
+        }
+    }
 }
 
 impl<Bytes: AllocBytes> Allocation<AllocId, (), Bytes> {
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 055d8e9a352..2435bc59ec0 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -5,11 +5,15 @@ use crate::query::TyCtxtAt;
 use crate::ty::{layout, tls, Ty, ValTree};
 
 use rustc_data_structures::sync::Lock;
-use rustc_errors::{pluralize, struct_span_err, DiagnosticBuilder, ErrorGuaranteed};
+use rustc_errors::{
+    struct_span_err, DiagnosticArgValue, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed,
+    IntoDiagnosticArg,
+};
 use rustc_macros::HashStable;
 use rustc_session::CtfeBacktrace;
 use rustc_span::def_id::DefId;
-use rustc_target::abi::{call, Align, Size};
+use rustc_target::abi::{call, Align, Size, WrappingRange};
+use std::borrow::Cow;
 use std::{any::Any, backtrace::Backtrace, fmt};
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable, TyEncodable, TyDecodable)]
@@ -91,21 +95,54 @@ pub struct InterpErrorInfo<'tcx>(Box<InterpErrorInfoInner<'tcx>>);
 #[derive(Debug)]
 struct InterpErrorInfoInner<'tcx> {
     kind: InterpError<'tcx>,
+    backtrace: InterpErrorBacktrace,
+}
+
+#[derive(Debug)]
+pub struct InterpErrorBacktrace {
     backtrace: Option<Box<Backtrace>>,
 }
 
-impl fmt::Display for InterpErrorInfo<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", self.0.kind)
+impl InterpErrorBacktrace {
+    pub fn new() -> InterpErrorBacktrace {
+        let capture_backtrace = tls::with_opt(|tcx| {
+            if let Some(tcx) = tcx {
+                *Lock::borrow(&tcx.sess.ctfe_backtrace)
+            } else {
+                CtfeBacktrace::Disabled
+            }
+        });
+
+        let backtrace = match capture_backtrace {
+            CtfeBacktrace::Disabled => None,
+            CtfeBacktrace::Capture => Some(Box::new(Backtrace::force_capture())),
+            CtfeBacktrace::Immediate => {
+                // Print it now.
+                let backtrace = Backtrace::force_capture();
+                print_backtrace(&backtrace);
+                None
+            }
+        };
+
+        InterpErrorBacktrace { backtrace }
     }
-}
 
-impl<'tcx> InterpErrorInfo<'tcx> {
     pub fn print_backtrace(&self) {
-        if let Some(backtrace) = self.0.backtrace.as_ref() {
+        if let Some(backtrace) = self.backtrace.as_ref() {
             print_backtrace(backtrace);
         }
     }
+}
+
+impl<'tcx> InterpErrorInfo<'tcx> {
+    pub fn from_parts(kind: InterpError<'tcx>, backtrace: InterpErrorBacktrace) -> Self {
+        Self(Box::new(InterpErrorInfoInner { kind, backtrace }))
+    }
+
+    pub fn into_parts(self) -> (InterpError<'tcx>, InterpErrorBacktrace) {
+        let InterpErrorInfo(box InterpErrorInfoInner { kind, backtrace }) = self;
+        (kind, backtrace)
+    }
 
     pub fn into_kind(self) -> InterpError<'tcx> {
         let InterpErrorInfo(box InterpErrorInfoInner { kind, .. }) = self;
@@ -130,32 +167,17 @@ impl From<ErrorGuaranteed> for InterpErrorInfo<'_> {
 
 impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> {
     fn from(kind: InterpError<'tcx>) -> Self {
-        let capture_backtrace = tls::with_opt(|tcx| {
-            if let Some(tcx) = tcx {
-                *Lock::borrow(&tcx.sess.ctfe_backtrace)
-            } else {
-                CtfeBacktrace::Disabled
-            }
-        });
-
-        let backtrace = match capture_backtrace {
-            CtfeBacktrace::Disabled => None,
-            CtfeBacktrace::Capture => Some(Box::new(Backtrace::force_capture())),
-            CtfeBacktrace::Immediate => {
-                // Print it now.
-                let backtrace = Backtrace::force_capture();
-                print_backtrace(&backtrace);
-                None
-            }
-        };
-
-        InterpErrorInfo(Box::new(InterpErrorInfoInner { kind, backtrace }))
+        InterpErrorInfo(Box::new(InterpErrorInfoInner {
+            kind,
+            backtrace: InterpErrorBacktrace::new(),
+        }))
     }
 }
 
 /// Error information for when the program we executed turned out not to actually be a valid
 /// program. This cannot happen in stand-alone Miri, but it can happen during CTFE/ConstProp
 /// where we work on generic code or execution does not have all information available.
+#[derive(Debug)]
 pub enum InvalidProgramInfo<'tcx> {
     /// Resolution can fail if we are in a too generic context.
     TooGeneric,
@@ -174,25 +196,6 @@ pub enum InvalidProgramInfo<'tcx> {
     UninitUnsizedLocal,
 }
 
-impl fmt::Display for InvalidProgramInfo<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use InvalidProgramInfo::*;
-        match self {
-            TooGeneric => write!(f, "encountered overly generic constant"),
-            AlreadyReported(_) => {
-                write!(
-                    f,
-                    "an error has already been reported elsewhere (this should not usually be printed)"
-                )
-            }
-            Layout(ref err) => write!(f, "{err}"),
-            FnAbiAdjustForForeignAbi(ref err) => write!(f, "{err}"),
-            SizeOfUnsizedType(ty) => write!(f, "size_of called on unsized type `{ty}`"),
-            UninitUnsizedLocal => write!(f, "unsized local is used while uninitialized"),
-        }
-    }
-}
-
 /// Details of why a pointer had to be in-bounds.
 #[derive(Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
 pub enum CheckInAllocMsg {
@@ -208,26 +211,25 @@ pub enum CheckInAllocMsg {
     InboundsTest,
 }
 
-impl fmt::Display for CheckInAllocMsg {
-    /// When this is printed as an error the context looks like this:
-    /// "{msg}{pointer} is a dangling pointer".
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(
-            f,
-            "{}",
-            match *self {
-                CheckInAllocMsg::DerefTest => "dereferencing pointer failed: ",
-                CheckInAllocMsg::MemoryAccessTest => "memory access failed: ",
-                CheckInAllocMsg::PointerArithmeticTest => "out-of-bounds pointer arithmetic: ",
-                CheckInAllocMsg::OffsetFromTest => "out-of-bounds offset_from: ",
-                CheckInAllocMsg::InboundsTest => "out-of-bounds pointer use: ",
-            }
-        )
+#[derive(Debug, Copy, Clone, TyEncodable, TyDecodable, HashStable)]
+pub enum InvalidMetaKind {
+    /// Size of a `[T]` is too big
+    SliceTooBig,
+    /// Size of a DST is too big
+    TooBig,
+}
+
+impl IntoDiagnosticArg for InvalidMetaKind {
+    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+        DiagnosticArgValue::Str(Cow::Borrowed(match self {
+            InvalidMetaKind::SliceTooBig => "slice_too_big",
+            InvalidMetaKind::TooBig => "too_big",
+        }))
     }
 }
 
 /// Details of an access to uninitialized bytes where it is not allowed.
-#[derive(Debug)]
+#[derive(Debug, Clone, Copy)]
 pub struct UninitBytesAccess {
     /// Range of the original memory access.
     pub access: AllocRange,
@@ -242,17 +244,32 @@ pub struct ScalarSizeMismatch {
     pub data_size: u64,
 }
 
+macro_rules! impl_into_diagnostic_arg_through_debug {
+    ($($ty:ty),*$(,)?) => {$(
+        impl IntoDiagnosticArg for $ty {
+            fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+                DiagnosticArgValue::Str(Cow::Owned(format!("{self:?}")))
+            }
+        }
+    )*}
+}
+
+// These types have nice `Debug` output so we can just use them in diagnostics.
+impl_into_diagnostic_arg_through_debug! {
+    AllocId,
+    Pointer,
+    AllocRange,
+}
+
 /// Error information for when the program caused Undefined Behavior.
-pub enum UndefinedBehaviorInfo {
-    /// Free-form case. Only for errors that are never caught!
+#[derive(Debug)]
+pub enum UndefinedBehaviorInfo<'a> {
+    /// Free-form case. Only for errors that are never caught! Used by miri
     Ub(String),
     /// Unreachable code was executed.
     Unreachable,
     /// A slice/array index projection went out-of-bounds.
-    BoundsCheckFailed {
-        len: u64,
-        index: u64,
-    },
+    BoundsCheckFailed { len: u64, index: u64 },
     /// Something was divided by 0 (x / 0).
     DivisionByZero,
     /// Something was "remainded" by 0 (x % 0).
@@ -263,8 +280,8 @@ pub enum UndefinedBehaviorInfo {
     RemainderOverflow,
     /// Overflowing inbounds pointer arithmetic.
     PointerArithOverflow,
-    /// Invalid metadata in a wide pointer (using `str` to avoid allocations).
-    InvalidMeta(&'static str),
+    /// Invalid metadata in a wide pointer
+    InvalidMeta(InvalidMetaKind),
     /// Reading a C string that does not end within its allocation.
     UnterminatedCString(Pointer),
     /// Dereferencing a dangling pointer after it got freed.
@@ -281,25 +298,13 @@ pub enum UndefinedBehaviorInfo {
     /// Using an integer as a pointer in the wrong way.
     DanglingIntPointer(u64, CheckInAllocMsg),
     /// Used a pointer with bad alignment.
-    AlignmentCheckFailed {
-        required: Align,
-        has: Align,
-    },
+    AlignmentCheckFailed { required: Align, has: Align },
     /// Writing to read-only memory.
     WriteToReadOnly(AllocId),
-    // Trying to access the data behind a function pointer.
+    /// Trying to access the data behind a function pointer.
     DerefFunctionPointer(AllocId),
-    // Trying to access the data behind a vtable pointer.
+    /// Trying to access the data behind a vtable pointer.
     DerefVTablePointer(AllocId),
-    /// The value validity check found a problem.
-    /// Should only be thrown by `validity.rs` and always point out which part of the value
-    /// is the problem.
-    ValidationFailure {
-        /// The "path" to the value in question, e.g. `.0[5].field` for a struct
-        /// field in the 6th element of an array that is the first element of a tuple.
-        path: Option<String>,
-        msg: String,
-    },
     /// Using a non-boolean `u8` as bool.
     InvalidBool(u8),
     /// Using a non-character `u32` as character.
@@ -320,110 +325,100 @@ pub enum UndefinedBehaviorInfo {
     ScalarSizeMismatch(ScalarSizeMismatch),
     /// A discriminant of an uninhabited enum variant is written.
     UninhabitedEnumVariantWritten,
+    /// Validation error.
+    Validation(ValidationErrorInfo<'a>),
+    // FIXME(fee1-dead) these should all be actual variants of the enum instead of dynamically
+    // dispatched
+    /// A custom (free-form) error, created by `err_ub_custom!`.
+    Custom(crate::error::CustomSubdiagnostic<'a>),
+}
+
+#[derive(Debug, Clone, Copy)]
+pub enum PointerKind {
+    Ref,
+    Box,
+}
+
+impl IntoDiagnosticArg for PointerKind {
+    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+        DiagnosticArgValue::Str(
+            match self {
+                Self::Ref => "ref",
+                Self::Box => "box",
+            }
+            .into(),
+        )
+    }
 }
 
-impl fmt::Display for UndefinedBehaviorInfo {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use UndefinedBehaviorInfo::*;
-        match self {
-            Ub(msg) => write!(f, "{msg}"),
-            Unreachable => write!(f, "entering unreachable code"),
-            BoundsCheckFailed { ref len, ref index } => {
-                write!(f, "indexing out of bounds: the len is {len} but the index is {index}")
-            }
-            DivisionByZero => write!(f, "dividing by zero"),
-            RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"),
-            DivisionOverflow => write!(f, "overflow in signed division (dividing MIN by -1)"),
-            RemainderOverflow => write!(f, "overflow in signed remainder (dividing MIN by -1)"),
-            PointerArithOverflow => write!(f, "overflowing in-bounds pointer arithmetic"),
-            InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {msg}"),
-            UnterminatedCString(p) => write!(
-                f,
-                "reading a null-terminated string starting at {p:?} with no null found before end of allocation",
-            ),
-            PointerUseAfterFree(a) => {
-                write!(f, "pointer to {a:?} was dereferenced after this allocation got freed")
-            }
-            PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size: Size::ZERO, msg } => {
-                write!(
-                    f,
-                    "{msg}{alloc_id:?} has size {alloc_size}, so pointer at offset {ptr_offset} is out-of-bounds",
-                    alloc_size = alloc_size.bytes(),
-                )
-            }
-            PointerOutOfBounds { alloc_id, alloc_size, ptr_offset, ptr_size, msg } => write!(
-                f,
-                "{msg}{alloc_id:?} has size {alloc_size}, so pointer to {ptr_size} byte{ptr_size_p} starting at offset {ptr_offset} is out-of-bounds",
-                alloc_size = alloc_size.bytes(),
-                ptr_size = ptr_size.bytes(),
-                ptr_size_p = pluralize!(ptr_size.bytes()),
-            ),
-            DanglingIntPointer(i, msg) => {
-                write!(
-                    f,
-                    "{msg}{pointer} is a dangling pointer (it has no provenance)",
-                    pointer = Pointer::<Option<AllocId>>::from_addr_invalid(*i),
-                )
-            }
-            AlignmentCheckFailed { required, has } => write!(
-                f,
-                "accessing memory with alignment {has}, but alignment {required} is required",
-                has = has.bytes(),
-                required = required.bytes()
-            ),
-            WriteToReadOnly(a) => write!(f, "writing to {a:?} which is read-only"),
-            DerefFunctionPointer(a) => write!(f, "accessing {a:?} which contains a function"),
-            DerefVTablePointer(a) => write!(f, "accessing {a:?} which contains a vtable"),
-            ValidationFailure { path: None, msg } => {
-                write!(f, "constructing invalid value: {msg}")
-            }
-            ValidationFailure { path: Some(path), msg } => {
-                write!(f, "constructing invalid value at {path}: {msg}")
-            }
-            InvalidBool(b) => {
-                write!(f, "interpreting an invalid 8-bit value as a bool: 0x{b:02x}")
-            }
-            InvalidChar(c) => {
-                write!(f, "interpreting an invalid 32-bit value as a char: 0x{c:08x}")
-            }
-            InvalidTag(val) => write!(f, "enum value has invalid tag: {val:x}"),
-            InvalidFunctionPointer(p) => {
-                write!(f, "using {p:?} as function pointer but it does not point to a function")
-            }
-            InvalidVTablePointer(p) => {
-                write!(f, "using {p:?} as vtable pointer but it does not point to a vtable")
-            }
-            InvalidStr(err) => write!(f, "this string is not valid UTF-8: {err}"),
-            InvalidUninitBytes(Some((alloc, info))) => write!(
-                f,
-                "reading memory at {alloc:?}{access:?}, \
-                 but memory is uninitialized at {uninit:?}, \
-                 and this operation requires initialized memory",
-                access = info.access,
-                uninit = info.uninit,
-            ),
-            InvalidUninitBytes(None) => write!(
-                f,
-                "using uninitialized data, but this operation requires initialized memory"
-            ),
-            DeadLocal => write!(f, "accessing a dead local variable"),
-            ScalarSizeMismatch(self::ScalarSizeMismatch { target_size, data_size }) => write!(
-                f,
-                "scalar size mismatch: expected {target_size} bytes but got {data_size} bytes instead",
-            ),
-            UninhabitedEnumVariantWritten => {
-                write!(f, "writing discriminant of an uninhabited enum")
-            }
+#[derive(Debug)]
+pub struct ValidationErrorInfo<'tcx> {
+    pub path: Option<String>,
+    pub kind: ValidationErrorKind<'tcx>,
+}
+
+#[derive(Debug)]
+pub enum ExpectedKind {
+    Reference,
+    Box,
+    RawPtr,
+    InitScalar,
+    Bool,
+    Char,
+    Float,
+    Int,
+    FnPtr,
+}
+
+impl From<PointerKind> for ExpectedKind {
+    fn from(x: PointerKind) -> ExpectedKind {
+        match x {
+            PointerKind::Box => ExpectedKind::Box,
+            PointerKind::Ref => ExpectedKind::Reference,
         }
     }
 }
 
+#[derive(Debug)]
+pub enum ValidationErrorKind<'tcx> {
+    PtrToUninhabited { ptr_kind: PointerKind, ty: Ty<'tcx> },
+    PtrToStatic { ptr_kind: PointerKind },
+    PtrToMut { ptr_kind: PointerKind },
+    ExpectedNonPtr { value: String },
+    MutableRefInConst,
+    NullFnPtr,
+    NeverVal,
+    NullablePtrOutOfRange { range: WrappingRange, max_value: u128 },
+    PtrOutOfRange { range: WrappingRange, max_value: u128 },
+    OutOfRange { value: String, range: WrappingRange, max_value: u128 },
+    UnsafeCell,
+    UninhabitedVal { ty: Ty<'tcx> },
+    InvalidEnumTag { value: String },
+    UninitEnumTag,
+    UninitStr,
+    Uninit { expected: ExpectedKind },
+    UninitVal,
+    InvalidVTablePtr { value: String },
+    InvalidMetaSliceTooLarge { ptr_kind: PointerKind },
+    InvalidMetaTooLarge { ptr_kind: PointerKind },
+    UnalignedPtr { ptr_kind: PointerKind, required_bytes: u64, found_bytes: u64 },
+    NullPtr { ptr_kind: PointerKind },
+    DanglingPtrNoProvenance { ptr_kind: PointerKind, pointer: String },
+    DanglingPtrOutOfBounds { ptr_kind: PointerKind },
+    DanglingPtrUseAfterFree { ptr_kind: PointerKind },
+    InvalidBool { value: String },
+    InvalidChar { value: String },
+    InvalidFnPtr { value: String },
+}
+
 /// Error information for when the program did something that might (or might not) be correct
 /// to do according to the Rust spec, but due to limitations in the interpreter, the
 /// operation could not be carried out. These limitations can differ between CTFE and the
 /// Miri engine, e.g., CTFE does not support dereferencing pointers at integral addresses.
+#[derive(Debug)]
 pub enum UnsupportedOpInfo {
     /// Free-form case. Only for errors that are never caught!
+    // FIXME still use translatable diagnostics
     Unsupported(String),
     //
     // The variants below are only reachable from CTFE/const prop, miri will never emit them.
@@ -442,83 +437,42 @@ pub enum UnsupportedOpInfo {
     ReadExternStatic(DefId),
 }
 
-impl fmt::Display for UnsupportedOpInfo {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use UnsupportedOpInfo::*;
-        match self {
-            Unsupported(ref msg) => write!(f, "{msg}"),
-            PartialPointerOverwrite(ptr) => {
-                write!(f, "unable to overwrite parts of a pointer in memory at {ptr:?}")
-            }
-            PartialPointerCopy(ptr) => {
-                write!(f, "unable to copy parts of a pointer from memory at {ptr:?}")
-            }
-            ReadPointerAsBytes => write!(f, "unable to turn pointer into raw bytes"),
-            ThreadLocalStatic(did) => write!(f, "cannot access thread local static ({did:?})"),
-            ReadExternStatic(did) => write!(f, "cannot read from extern static ({did:?})"),
-        }
-    }
-}
-
 /// Error information for when the program exhausted the resources granted to it
 /// by the interpreter.
+#[derive(Debug)]
 pub enum ResourceExhaustionInfo {
     /// The stack grew too big.
     StackFrameLimitReached,
-    /// The program ran for too long.
-    ///
-    /// The exact limit is set by the `const_eval_limit` attribute.
-    StepLimitReached,
     /// There is not enough memory (on the host) to perform an allocation.
     MemoryExhausted,
     /// The address space (of the target) is full.
     AddressSpaceFull,
 }
 
-impl fmt::Display for ResourceExhaustionInfo {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use ResourceExhaustionInfo::*;
-        match self {
-            StackFrameLimitReached => {
-                write!(f, "reached the configured maximum number of stack frames")
-            }
-            StepLimitReached => {
-                write!(f, "exceeded interpreter step limit (see `#[const_eval_limit]`)")
-            }
-            MemoryExhausted => {
-                write!(f, "tried to allocate more memory than available to compiler")
-            }
-            AddressSpaceFull => {
-                write!(f, "there are no more free addresses in the address space")
-            }
-        }
-    }
-}
-
-/// A trait to work around not having trait object upcasting.
-pub trait AsAny: Any {
-    fn as_any(&self) -> &dyn Any;
-}
-impl<T: Any> AsAny for T {
-    #[inline(always)]
-    fn as_any(&self) -> &dyn Any {
-        self
-    }
-}
-
 /// A trait for machine-specific errors (or other "machine stop" conditions).
-pub trait MachineStopType: AsAny + fmt::Display + Send {}
+pub trait MachineStopType: Any + fmt::Debug + Send {
+    /// The diagnostic message for this error
+    fn diagnostic_message(&self) -> DiagnosticMessage;
+    /// Add diagnostic arguments by passing name and value pairs to `adder`, which are passed to
+    /// fluent for formatting the translated diagnostic message.
+    fn add_args(
+        self: Box<Self>,
+        adder: &mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue<'static>),
+    );
+}
 
 impl dyn MachineStopType {
     #[inline(always)]
     pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
-        self.as_any().downcast_ref()
+        let x: &dyn Any = self;
+        x.downcast_ref()
     }
 }
 
+#[derive(Debug)]
 pub enum InterpError<'tcx> {
     /// The program caused undefined behavior.
-    UndefinedBehavior(UndefinedBehaviorInfo),
+    UndefinedBehavior(UndefinedBehaviorInfo<'tcx>),
     /// The program did something the interpreter does not support (some of these *might* be UB
     /// but the interpreter is not sure).
     Unsupported(UnsupportedOpInfo),
@@ -534,26 +488,6 @@ pub enum InterpError<'tcx> {
 
 pub type InterpResult<'tcx, T = ()> = Result<T, InterpErrorInfo<'tcx>>;
 
-impl fmt::Display for InterpError<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use InterpError::*;
-        match *self {
-            Unsupported(ref msg) => write!(f, "{msg}"),
-            InvalidProgram(ref msg) => write!(f, "{msg}"),
-            UndefinedBehavior(ref msg) => write!(f, "{msg}"),
-            ResourceExhaustion(ref msg) => write!(f, "{msg}"),
-            MachineStop(ref msg) => write!(f, "{msg}"),
-        }
-    }
-}
-
-// Forward `Debug` to `Display`, so it does not look awful.
-impl fmt::Debug for InterpError<'_> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(self, f)
-    }
-}
-
 impl InterpError<'_> {
     /// Some errors do string formatting even if the error is never printed.
     /// To avoid performance issues, there are places where we want to be sure to never raise these formatting errors,
@@ -562,7 +496,7 @@ impl InterpError<'_> {
         matches!(
             self,
             InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_))
-                | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::ValidationFailure { .. })
+                | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Validation { .. })
                 | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_))
         )
     }
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index 3620385fab1..2d2cfee1b21 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -89,6 +89,30 @@ macro_rules! throw_machine_stop {
     ($($tt:tt)*) => { do yeet err_machine_stop!($($tt)*) };
 }
 
+#[macro_export]
+macro_rules! err_ub_custom {
+    ($msg:expr $(, $($name:ident = $value:expr),* $(,)?)?) => {{
+        $(
+            let ($($name,)*) = ($($value,)*);
+        )?
+        err_ub!(Custom(
+            rustc_middle::error::CustomSubdiagnostic {
+                msg: || $msg,
+                add_args: Box::new(move |mut set_arg| {
+                    $($(
+                        set_arg(stringify!($name).into(), rustc_errors::IntoDiagnosticArg::into_diagnostic_arg($name));
+                    )*)?
+                })
+            }
+        ))
+    }};
+}
+
+#[macro_export]
+macro_rules! throw_ub_custom {
+    ($($tt:tt)*) => { do yeet err_ub_custom!($($tt)*) };
+}
+
 mod allocation;
 mod error;
 mod pointer;
@@ -119,9 +143,10 @@ use crate::ty::{self, Instance, Ty, TyCtxt};
 
 pub use self::error::{
     struct_error, CheckInAllocMsg, ErrorHandled, EvalToAllocationRawResult, EvalToConstValueResult,
-    EvalToValTreeResult, InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo,
-    MachineStopType, ReportedErrorInfo, ResourceExhaustionInfo, ScalarSizeMismatch,
-    UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo,
+    EvalToValTreeResult, ExpectedKind, InterpError, InterpErrorInfo, InterpResult, InvalidMetaKind,
+    InvalidProgramInfo, MachineStopType, PointerKind, ReportedErrorInfo, ResourceExhaustionInfo,
+    ScalarSizeMismatch, UndefinedBehaviorInfo, UninitBytesAccess, UnsupportedOpInfo,
+    ValidationErrorInfo, ValidationErrorKind,
 };
 
 pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar};
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index 36dbbe4bf77..91caf9db336 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -375,7 +375,8 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
     #[inline(always)]
     #[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
     pub fn assert_bits(self, target_size: Size) -> u128 {
-        self.to_bits(target_size).unwrap()
+        self.to_bits(target_size)
+            .unwrap_or_else(|_| panic!("assertion failed: {self:?} fits {target_size:?}"))
     }
 
     pub fn to_bool(self) -> InterpResult<'tcx, bool> {
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 63cdba7f327..e929240bf30 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -3,7 +3,7 @@
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html
 
 use crate::mir::interpret::{
-    AllocRange, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, LitToConstInput, Scalar,
+    AllocRange, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
 };
 use crate::mir::visit::MirVisitable;
 use crate::ty::codec::{TyDecoder, TyEncoder};
@@ -15,7 +15,7 @@ use crate::ty::{AdtDef, InstanceDef, ScalarInt, UserTypeAnnotationIndex};
 use crate::ty::{GenericArg, InternalSubsts, SubstsRef};
 
 use rustc_data_structures::captures::Captures;
-use rustc_errors::ErrorGuaranteed;
+use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg};
 use rustc_hir::def::{CtorKind, Namespace};
 use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
 use rustc_hir::{self, GeneratorKind, ImplicitSelfKind};
@@ -1371,55 +1371,61 @@ impl<O> AssertKind<O> {
             _ => write!(f, "\"{}\"", self.description()),
         }
     }
-}
 
-impl<O: fmt::Debug> fmt::Debug for AssertKind<O> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+    pub fn diagnostic_message(&self) -> DiagnosticMessage {
+        use crate::fluent_generated::*;
         use AssertKind::*;
+
         match self {
-            BoundsCheck { ref len, ref index } => write!(
-                f,
-                "index out of bounds: the length is {:?} but the index is {:?}",
-                len, index
-            ),
-            OverflowNeg(op) => write!(f, "attempt to negate `{:#?}`, which would overflow", op),
-            DivisionByZero(op) => write!(f, "attempt to divide `{:#?}` by zero", op),
-            RemainderByZero(op) => write!(
-                f,
-                "attempt to calculate the remainder of `{:#?}` with a divisor of zero",
-                op
-            ),
-            Overflow(BinOp::Add, l, r) => {
-                write!(f, "attempt to compute `{:#?} + {:#?}`, which would overflow", l, r)
-            }
-            Overflow(BinOp::Sub, l, r) => {
-                write!(f, "attempt to compute `{:#?} - {:#?}`, which would overflow", l, r)
-            }
-            Overflow(BinOp::Mul, l, r) => {
-                write!(f, "attempt to compute `{:#?} * {:#?}`, which would overflow", l, r)
-            }
-            Overflow(BinOp::Div, l, r) => {
-                write!(f, "attempt to compute `{:#?} / {:#?}`, which would overflow", l, r)
+            BoundsCheck { .. } => middle_bounds_check,
+            Overflow(BinOp::Shl, _, _) => middle_assert_shl_overflow,
+            Overflow(BinOp::Shr, _, _) => middle_assert_shr_overflow,
+            Overflow(_, _, _) => middle_assert_op_overflow,
+            OverflowNeg(_) => middle_assert_overflow_neg,
+            DivisionByZero(_) => middle_assert_divide_by_zero,
+            RemainderByZero(_) => middle_assert_remainder_by_zero,
+            ResumedAfterReturn(GeneratorKind::Async(_)) => middle_assert_async_resume_after_return,
+            ResumedAfterReturn(GeneratorKind::Gen) => middle_assert_generator_resume_after_return,
+            ResumedAfterPanic(GeneratorKind::Async(_)) => middle_assert_async_resume_after_panic,
+            ResumedAfterPanic(GeneratorKind::Gen) => middle_assert_generator_resume_after_panic,
+
+            MisalignedPointerDereference { .. } => middle_assert_misaligned_ptr_deref,
+        }
+    }
+
+    pub fn add_args(self, adder: &mut dyn FnMut(Cow<'static, str>, DiagnosticArgValue<'static>))
+    where
+        O: fmt::Debug,
+    {
+        use AssertKind::*;
+
+        macro_rules! add {
+            ($name: expr, $value: expr) => {
+                adder($name.into(), $value.into_diagnostic_arg());
+            };
+        }
+
+        match self {
+            BoundsCheck { len, index } => {
+                add!("len", format!("{len:?}"));
+                add!("index", format!("{index:?}"));
             }
-            Overflow(BinOp::Rem, l, r) => write!(
-                f,
-                "attempt to compute the remainder of `{:#?} % {:#?}`, which would overflow",
-                l, r
-            ),
-            Overflow(BinOp::Shr, _, r) => {
-                write!(f, "attempt to shift right by `{:#?}`, which would overflow", r)
+            Overflow(BinOp::Shl | BinOp::Shr, _, val)
+            | DivisionByZero(val)
+            | RemainderByZero(val)
+            | OverflowNeg(val) => {
+                add!("val", format!("{val:#?}"));
             }
-            Overflow(BinOp::Shl, _, r) => {
-                write!(f, "attempt to shift left by `{:#?}`, which would overflow", r)
+            Overflow(binop, left, right) => {
+                add!("op", binop.to_hir_binop().as_str());
+                add!("left", format!("{left:#?}"));
+                add!("right", format!("{right:#?}"));
             }
+            ResumedAfterReturn(_) | ResumedAfterPanic(_) => {}
             MisalignedPointerDereference { required, found } => {
-                write!(
-                    f,
-                    "misaligned pointer dereference: address must be a multiple of {:?} but is {:?}",
-                    required, found
-                )
+                add!("required", format!("{required:#?}"));
+                add!("found", format!("{found:#?}"));
             }
-            _ => write!(f, "{}", self.description()),
         }
     }
 }
@@ -2461,51 +2467,6 @@ impl<'tcx> ConstantKind<'tcx> {
         Self::Val(val, ty)
     }
 
-    #[instrument(skip(tcx), level = "debug", ret)]
-    pub fn from_inline_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
-        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
-        let body_id = match tcx.hir().get(hir_id) {
-            hir::Node::AnonConst(ac) => ac.body,
-            _ => span_bug!(
-                tcx.def_span(def_id.to_def_id()),
-                "from_inline_const can only process anonymous constants"
-            ),
-        };
-        let expr = &tcx.hir().body(body_id).value;
-        let ty = tcx.typeck(def_id).node_type(hir_id);
-
-        let lit_input = match expr.kind {
-            hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
-            hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind {
-                hir::ExprKind::Lit(ref lit) => {
-                    Some(LitToConstInput { lit: &lit.node, ty, neg: true })
-                }
-                _ => None,
-            },
-            _ => None,
-        };
-        if let Some(lit_input) = lit_input {
-            // If an error occurred, ignore that it's a literal and leave reporting the error up to
-            // mir.
-            match tcx.at(expr.span).lit_to_mir_constant(lit_input) {
-                Ok(c) => return c,
-                Err(_) => {}
-            }
-        }
-
-        let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id());
-        let parent_substs =
-            tcx.erase_regions(InternalSubsts::identity_for_item(tcx, typeck_root_def_id));
-        let substs =
-            ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
-                .substs;
-
-        let uneval = UnevaluatedConst { def: def_id.to_def_id(), substs, promoted: None };
-        debug_assert!(!uneval.has_free_regions());
-
-        Self::Unevaluated(uneval, ty)
-    }
-
     /// Literals are converted to `ConstantKindVal`, const generic parameters are eagerly
     /// converted to a constant, everything else becomes `Unevaluated`.
     #[instrument(skip(tcx), level = "debug", ret)]
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 62c3d8cf239..8477722ea39 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -846,7 +846,7 @@ fn write_allocation_newline(
 /// The `prefix` argument allows callers to add an arbitrary prefix before each line (even if there
 /// is only one line). Note that your prefix should contain a trailing space as the lines are
 /// printed directly after it.
-fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
+pub fn write_allocation_bytes<'tcx, Prov: Provenance, Extra, Bytes: AllocBytes>(
     tcx: TyCtxt<'tcx>,
     alloc: &Allocation<Prov, Extra, Bytes>,
     w: &mut dyn std::fmt::Write,
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 3e474c1d377..83f8f00d72c 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -801,7 +801,8 @@ pub enum UnwindAction {
 }
 
 /// Information about an assertion failure.
-#[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)]
+#[derive(Clone, Hash, HashStable, PartialEq, Debug)]
+#[derive(TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)]
 pub enum AssertKind<O> {
     BoundsCheck { len: O, index: O },
     Overflow(BinOp, O, O),
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 1528be42f6a..0b31c9bbf81 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1081,14 +1081,6 @@ rustc_queries! {
         desc { "destructuring MIR constant"}
     }
 
-    /// Dereference a constant reference or raw pointer and turn the result into a constant
-    /// again.
-    query deref_mir_constant(
-        key: ty::ParamEnvAnd<'tcx, mir::ConstantKind<'tcx>>
-    ) -> mir::ConstantKind<'tcx> {
-        desc { "dereferencing MIR constant" }
-    }
-
     query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> {
         desc { "getting a &core::panic::Location referring to a span" }
     }
@@ -1100,10 +1092,6 @@ rustc_queries! {
         desc { "converting literal to const" }
     }
 
-    query lit_to_mir_constant(key: LitToConstInput<'tcx>) -> Result<mir::ConstantKind<'tcx>, LitToConstError> {
-        desc { "converting literal to mir constant" }
-    }
-
     query check_match(key: LocalDefId) -> Result<(), rustc_errors::ErrorGuaranteed> {
         desc { |tcx| "match-checking `{}`", tcx.def_path_str(key) }
         cache_on_disk_if { true }
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index d1dbc531edf..1e43fab457e 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -1,5 +1,6 @@
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
+use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use rustc_target::abi::Size;
 use std::fmt;
@@ -113,6 +114,14 @@ impl std::fmt::Debug for ConstInt {
     }
 }
 
+impl IntoDiagnosticArg for ConstInt {
+    // FIXME this simply uses the Debug impl, but we could probably do better by converting both
+    // to an inherent method that returns `Cow`.
+    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+        DiagnosticArgValue::Str(format!("{self:?}").into())
+    }
+}
+
 /// The raw bytes of a simple value.
 ///
 /// This is a packed struct in order to allow this type to be optimally embedded in enums
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 77725f0b3b6..b05e791211d 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -82,8 +82,6 @@ use std::iter;
 use std::mem;
 use std::ops::{Bound, Deref};
 
-const TINY_CONST_EVAL_LIMIT: Limit = Limit(20);
-
 #[allow(rustc::usage_of_ty_tykind)]
 impl<'tcx> Interner for TyCtxt<'tcx> {
     type AdtDef = ty::AdtDef<'tcx>;
@@ -1178,14 +1176,6 @@ impl<'tcx> TyCtxt<'tcx> {
         self.limits(()).move_size_limit
     }
 
-    pub fn const_eval_limit(self) -> Limit {
-        if self.sess.opts.unstable_opts.tiny_const_eval_limit {
-            TINY_CONST_EVAL_LIMIT
-        } else {
-            self.limits(()).const_eval_limit
-        }
-    }
-
     pub fn all_traits(self) -> impl Iterator<Item = DefId> + 'tcx {
         iter::once(LOCAL_CRATE)
             .chain(self.crates(()).iter().copied())
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index b5a743cfe34..c5a306fdf1f 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1,8 +1,9 @@
-use crate::fluent_generated as fluent;
+use crate::error::UnsupportedFnAbi;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::query::TyCtxtAt;
 use crate::ty::normalize_erasing_regions::NormalizationError;
 use crate::ty::{self, ReprOptions, Ty, TyCtxt, TypeVisitableExt};
+use rustc_error_messages::DiagnosticMessage;
 use rustc_errors::{DiagnosticBuilder, Handler, IntoDiagnostic};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -14,7 +15,7 @@ use rustc_target::abi::call::FnAbi;
 use rustc_target::abi::*;
 use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec, PanicStrategy, Target};
 
-use std::cmp::{self};
+use std::cmp;
 use std::fmt;
 use std::num::NonZeroUsize;
 use std::ops::Bound;
@@ -214,29 +215,29 @@ pub enum LayoutError<'tcx> {
     Cycle,
 }
 
-impl IntoDiagnostic<'_, !> for LayoutError<'_> {
-    fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
-        let mut diag = handler.struct_fatal("");
+impl<'tcx> LayoutError<'tcx> {
+    pub fn diagnostic_message(&self) -> DiagnosticMessage {
+        use crate::fluent_generated::*;
+        use LayoutError::*;
+        match self {
+            Unknown(_) => middle_unknown_layout,
+            SizeOverflow(_) => middle_values_too_big,
+            NormalizationFailure(_, _) => middle_cannot_be_normalized,
+            Cycle => middle_cycle,
+        }
+    }
 
+    pub fn into_diagnostic(self) -> crate::error::LayoutError<'tcx> {
+        use crate::error::LayoutError as E;
+        use LayoutError::*;
         match self {
-            LayoutError::Unknown(ty) => {
-                diag.set_arg("ty", ty);
-                diag.set_primary_message(fluent::middle_unknown_layout);
-            }
-            LayoutError::SizeOverflow(ty) => {
-                diag.set_arg("ty", ty);
-                diag.set_primary_message(fluent::middle_values_too_big);
-            }
-            LayoutError::NormalizationFailure(ty, e) => {
-                diag.set_arg("ty", ty);
-                diag.set_arg("failure_ty", e.get_type_for_failure());
-                diag.set_primary_message(fluent::middle_cannot_be_normalized);
-            }
-            LayoutError::Cycle => {
-                diag.set_primary_message(fluent::middle_cycle);
+            Unknown(ty) => E::Unknown { ty },
+            SizeOverflow(ty) => E::Overflow { ty },
+            NormalizationFailure(ty, e) => {
+                E::NormalizationFailure { ty, failure_ty: e.get_type_for_failure() }
             }
+            Cycle => E::Cycle,
         }
-        diag
     }
 }
 
@@ -330,11 +331,8 @@ impl<'tcx> SizeSkeleton<'tcx> {
                         Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
                     }
                     _ => bug!(
-                        "SizeSkeleton::compute({}): layout errored ({}), yet \
-                              tail `{}` is not a type parameter or a projection",
-                        ty,
-                        err,
-                        tail
+                        "SizeSkeleton::compute({ty}): layout errored ({err:?}), yet \
+                              tail `{tail}` is not a type parameter or a projection",
                     ),
                 }
             }
@@ -940,12 +938,8 @@ where
             TyMaybeWithLayout::Ty(field_ty) => {
                 cx.tcx().layout_of(cx.param_env().and(field_ty)).unwrap_or_else(|e| {
                     bug!(
-                        "failed to get layout for `{}`: {},\n\
-                         despite it being a field (#{}) of an existing layout: {:#?}",
-                        field_ty,
-                        e,
-                        i,
-                        this
+                        "failed to get layout for `{field_ty}`: {e:?},\n\
+                         despite it being a field (#{i}) of an existing layout: {this:#?}",
                     )
                 })
             }
@@ -1262,21 +1256,18 @@ impl From<call::AdjustForForeignAbiError> for FnAbiError<'_> {
     }
 }
 
-impl<'tcx> fmt::Display for FnAbiError<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+impl<'a, 'b> IntoDiagnostic<'a, !> for FnAbiError<'b> {
+    fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, !> {
         match self {
-            Self::Layout(err) => err.fmt(f),
-            Self::AdjustForForeignAbi(err) => err.fmt(f),
+            Self::Layout(e) => e.into_diagnostic().into_diagnostic(handler),
+            Self::AdjustForForeignAbi(call::AdjustForForeignAbiError::Unsupported {
+                arch,
+                abi,
+            }) => UnsupportedFnAbi { arch, abi: abi.name() }.into_diagnostic(handler),
         }
     }
 }
 
-impl IntoDiagnostic<'_, !> for FnAbiError<'_> {
-    fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder<'_, !> {
-        handler.struct_fatal(self.to_string())
-    }
-}
-
 // FIXME(eddyb) maybe use something like this for an unified `fn_abi_of`, not
 // just for error handling.
 #[derive(Debug)]
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index e04dbbff9a7..8cbffa14850 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -155,11 +155,7 @@ pub struct TypeckResults<'tcx> {
     /// We also store the type here, so that the compiler can use it as a hint
     /// for figuring out hidden types, even if they are only set in dead code
     /// (which doesn't show up in MIR).
-    ///
-    /// These types are mapped back to the opaque's identity substitutions
-    /// (with erased regions), which is why we don't associated substs with any
-    /// of these usages.
-    pub concrete_opaque_types: FxIndexMap<LocalDefId, ty::OpaqueHiddenType<'tcx>>,
+    pub concrete_opaque_types: FxIndexMap<ty::OpaqueTypeKey<'tcx>, ty::OpaqueHiddenType<'tcx>>,
 
     /// Tracks the minimum captures required for a closure;
     /// see `MinCaptureInformationMap` for more details.
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 311f63adc7f..dce2f5545f5 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -15,7 +15,7 @@ use rustc_data_structures::stable_hasher::{Hash64, HashStable, StableHasher};
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_index::{Idx, IndexVec};
 use rustc_macros::HashStable;
@@ -857,6 +857,26 @@ impl<'tcx> TyCtxt<'tcx> {
             _ => def_kind.article(),
         }
     }
+
+    /// Return `true` if the supplied `CrateNum` is "user-visible," meaning either a [public]
+    /// dependency, or a [direct] private dependency. This is used to decide whether the crate can
+    /// be shown in `impl` suggestions.
+    ///
+    /// [public]: TyCtxt::is_private_dep
+    /// [direct]: rustc_session::cstore::ExternCrate::is_direct
+    pub fn is_user_visible_dep(self, key: CrateNum) -> bool {
+        // | Private | Direct | Visible |                    |
+        // |---------|--------|---------|--------------------|
+        // | Yes     | Yes    | Yes     | !true || true   |
+        // | No      | Yes    | Yes     | !false || true  |
+        // | Yes     | No     | No      | !true || false  |
+        // | No      | No     | Yes     | !false || false |
+        !self.is_private_dep(key)
+            // If `extern_crate` is `None`, then the crate was injected (e.g., by the allocator).
+            // Treat that kind of crate as "indirect", since it's an implementation detail of
+            // the language.
+            || self.extern_crate(key.as_def_id()).map_or(false, |e| e.is_direct())
+    }
 }
 
 struct OpaqueTypeExpander<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/vtable.rs b/compiler/rustc_middle/src/ty/vtable.rs
index b9b1cd73a8b..443791d0af4 100644
--- a/compiler/rustc_middle/src/ty/vtable.rs
+++ b/compiler/rustc_middle/src/ty/vtable.rs
@@ -73,7 +73,7 @@ pub(super) fn vtable_allocation_provider<'tcx>(
     let ptr_align = tcx.data_layout.pointer_align.abi;
 
     let vtable_size = ptr_size * u64::try_from(vtable_entries.len()).unwrap();
-    let mut vtable = Allocation::uninit(vtable_size, ptr_align, /* panic_on_fail */ true).unwrap();
+    let mut vtable = Allocation::uninit(vtable_size, ptr_align);
 
     // No need to do any alignment checks on the memory accesses below, because we know the
     // allocation is correctly aligned as we created it above. Also we're only offsetting by
diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
index 4d99ab4b0ec..73d5eb62750 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -106,7 +106,7 @@ pub fn as_constant_inner<'tcx>(
 }
 
 #[instrument(skip(tcx, lit_input))]
-pub(crate) fn lit_to_mir_constant<'tcx>(
+fn lit_to_mir_constant<'tcx>(
     tcx: TyCtxt<'tcx>,
     lit_input: LitToConstInput<'tcx>,
 ) -> Result<ConstantKind<'tcx>, LitToConstError> {
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 4e3e98b56e7..8f6a069a7db 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -1,4 +1,3 @@
-pub(crate) use crate::build::expr::as_constant::lit_to_mir_constant;
 use crate::build::expr::as_place::PlaceBuilder;
 use crate::build::scope::DropKind;
 use rustc_apfloat::ieee::{Double, Single};
diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs
index c964e62c9d0..0eaab9b5703 100644
--- a/compiler/rustc_mir_build/src/lib.rs
+++ b/compiler/rustc_mir_build/src/lib.rs
@@ -32,7 +32,6 @@ fluent_messages! { "../messages.ftl" }
 pub fn provide(providers: &mut Providers) {
     providers.check_match = thir::pattern::check_match;
     providers.lit_to_const = thir::constant::lit_to_const;
-    providers.lit_to_mir_constant = build::lit_to_mir_constant;
     providers.mir_built = build::mir_built;
     providers.thir_check_unsafety = check_unsafety::thir_check_unsafety;
     providers.thir_body = thir::cx::thir_body;
diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs
index 57ae6a3652d..a7be8e3c903 100644
--- a/compiler/rustc_mir_build/src/thir/constant.rs
+++ b/compiler/rustc_mir_build/src/thir/constant.rs
@@ -3,6 +3,8 @@ use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
 use rustc_middle::ty::{self, ParamEnv, ScalarInt, TyCtxt};
 use rustc_span::DUMMY_SP;
 
+use crate::build::parse_float_into_scalar;
+
 pub(crate) fn lit_to_const<'tcx>(
     tcx: TyCtxt<'tcx>,
     lit_input: LitToConstInput<'tcx>,
@@ -46,12 +48,28 @@ pub(crate) fn lit_to_const<'tcx>(
         (ast::LitKind::Byte(n), ty::Uint(ty::UintTy::U8)) => {
             ty::ValTree::from_scalar_int((*n).into())
         }
+        (ast::LitKind::CStr(data, _), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Adt(def, _) if Some(def.did()) == tcx.lang_items().c_str()) =>
+        {
+            let bytes = data as &[u8];
+            ty::ValTree::from_raw_bytes(tcx, bytes)
+        }
         (ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
             let scalar_int =
                 trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?;
             ty::ValTree::from_scalar_int(scalar_int)
         }
         (ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int((*b).into()),
+        (ast::LitKind::Float(n, _), ty::Float(fty)) => {
+            let bits = parse_float_into_scalar(*n, *fty, neg)
+                .ok_or_else(|| {
+                    LitToConstError::Reported(tcx.sess.delay_span_bug(
+                        DUMMY_SP,
+                        format!("couldn't parse float literal: {:?}", lit_input.lit),
+                    ))
+                })?
+                .assert_int();
+            ty::ValTree::from_scalar_int(bits)
+        }
         (ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int((*c).into()),
         (ast::LitKind::Err, _) => {
             return Err(LitToConstError::Reported(
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index b243f1dc8d0..7976b148f75 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -1,13 +1,14 @@
 use rustc_hir as hir;
+use rustc_hir::def_id::DefId;
 use rustc_index::Idx;
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::Obligation;
 use rustc_middle::mir;
 use rustc_middle::thir::{FieldPat, Pat, PatKind};
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt, ValTree};
 use rustc_session::lint;
 use rustc_span::Span;
-use rustc_target::abi::FieldIdx;
+use rustc_target::abi::{FieldIdx, VariantIdx};
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::{self, ObligationCause};
 
@@ -29,11 +30,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         cv: mir::ConstantKind<'tcx>,
         id: hir::HirId,
         span: Span,
-        mir_structural_match_violation: bool,
+        check_body_for_struct_match_violation: Option<DefId>,
     ) -> Box<Pat<'tcx>> {
         let infcx = self.tcx.infer_ctxt().build();
         let mut convert = ConstToPat::new(self, id, span, infcx);
-        convert.to_pat(cv, mir_structural_match_violation)
+        convert.to_pat(cv, check_body_for_struct_match_violation)
     }
 }
 
@@ -104,7 +105,7 @@ impl<'tcx> ConstToPat<'tcx> {
     fn to_pat(
         &mut self,
         cv: mir::ConstantKind<'tcx>,
-        mir_structural_match_violation: bool,
+        check_body_for_struct_match_violation: Option<DefId>,
     ) -> Box<Pat<'tcx>> {
         trace!(self.treat_byte_string_as_slice);
         // This method is just a wrapper handling a validity check; the heavy lifting is
@@ -114,14 +115,44 @@ impl<'tcx> ConstToPat<'tcx> {
         // once indirect_structural_match is a full fledged error, this
         // level of indirection can be eliminated
 
-        let inlined_const_as_pat =
-            self.recur(cv, mir_structural_match_violation).unwrap_or_else(|_| {
-                Box::new(Pat {
-                    span: self.span,
-                    ty: cv.ty(),
-                    kind: PatKind::Constant { value: cv },
-                })
-            });
+        let mir_structural_match_violation = check_body_for_struct_match_violation.map(|def_id| {
+            // `mir_const_qualif` must be called with the `DefId` of the item where the const is
+            // defined, not where it is declared. The difference is significant for associated
+            // constants.
+            self.tcx().mir_const_qualif(def_id).custom_eq
+        });
+        debug!(?check_body_for_struct_match_violation, ?mir_structural_match_violation);
+
+        let inlined_const_as_pat = match cv {
+            mir::ConstantKind::Ty(c) => match c.kind() {
+                ty::ConstKind::Param(_)
+                | ty::ConstKind::Infer(_)
+                | ty::ConstKind::Bound(_, _)
+                | ty::ConstKind::Placeholder(_)
+                | ty::ConstKind::Unevaluated(_)
+                | ty::ConstKind::Error(_)
+                | ty::ConstKind::Expr(_) => {
+                    span_bug!(self.span, "unexpected const in `to_pat`: {:?}", c.kind())
+                }
+                ty::ConstKind::Value(valtree) => self
+                    .recur(valtree, cv.ty(), mir_structural_match_violation.unwrap_or(false))
+                    .unwrap_or_else(|_| {
+                        Box::new(Pat {
+                            span: self.span,
+                            ty: cv.ty(),
+                            kind: PatKind::Constant { value: cv },
+                        })
+                    }),
+            },
+            mir::ConstantKind::Unevaluated(_, _) => {
+                span_bug!(self.span, "unevaluated const in `to_pat`: {cv:?}")
+            }
+            mir::ConstantKind::Val(_, _) => Box::new(Pat {
+                span: self.span,
+                ty: cv.ty(),
+                kind: PatKind::Constant { value: cv },
+            }),
+        };
 
         if !self.saw_const_match_error.get() {
             // If we were able to successfully convert the const to some pat,
@@ -141,29 +172,70 @@ impl<'tcx> ConstToPat<'tcx> {
             //
             // FIXME(#73448): Find a way to bring const qualification into parity with
             // `search_for_structural_match_violation`.
-            if structural.is_none() && mir_structural_match_violation {
+            if structural.is_none() && mir_structural_match_violation.unwrap_or(false) {
                 warn!("MIR const-checker found novel structural match violation. See #73448.");
                 return inlined_const_as_pat;
             }
 
             if let Some(non_sm_ty) = structural {
                 if !self.type_may_have_partial_eq_impl(cv.ty()) {
-                    // fatal avoids ICE from resolution of nonexistent method (rare case).
-                    self.tcx()
-                        .sess
-                        .emit_fatal(TypeNotStructural { span: self.span, non_sm_ty: non_sm_ty });
-                } else if mir_structural_match_violation && !self.saw_const_match_lint.get() {
-                    self.tcx().emit_spanned_lint(
-                        lint::builtin::INDIRECT_STRUCTURAL_MATCH,
-                        self.id,
-                        self.span,
-                        IndirectStructuralMatch { non_sm_ty },
-                    );
-                } else {
-                    debug!(
-                        "`search_for_structural_match_violation` found one, but `CustomEq` was \
-                          not in the qualifs for that `const`"
-                    );
+                    if let ty::Adt(def, ..) = non_sm_ty.kind() {
+                        if def.is_union() {
+                            let err = UnionPattern { span: self.span };
+                            self.tcx().sess.emit_err(err);
+                        } else {
+                            // fatal avoids ICE from resolution of nonexistent method (rare case).
+                            self.tcx()
+                                .sess
+                                .emit_fatal(TypeNotStructural { span: self.span, non_sm_ty });
+                        }
+                    } else {
+                        let err = InvalidPattern { span: self.span, non_sm_ty };
+                        self.tcx().sess.emit_err(err);
+                        return Box::new(Pat { span: self.span, ty: cv.ty(), kind: PatKind::Wild });
+                    }
+                } else if !self.saw_const_match_lint.get() {
+                    if let Some(mir_structural_match_violation) = mir_structural_match_violation {
+                        match non_sm_ty.kind() {
+                            ty::RawPtr(pointee)
+                                if pointee.ty.is_sized(self.tcx(), self.param_env) => {}
+                            ty::FnPtr(..) | ty::RawPtr(..) => {
+                                self.tcx().emit_spanned_lint(
+                                    lint::builtin::POINTER_STRUCTURAL_MATCH,
+                                    self.id,
+                                    self.span,
+                                    PointerPattern,
+                                );
+                            }
+                            ty::Adt(..) if mir_structural_match_violation => {
+                                self.tcx().emit_spanned_lint(
+                                    lint::builtin::INDIRECT_STRUCTURAL_MATCH,
+                                    self.id,
+                                    self.span,
+                                    IndirectStructuralMatch { non_sm_ty },
+                                );
+                            }
+                            _ => {
+                                debug!(
+                                    "`search_for_structural_match_violation` found one, but `CustomEq` was \
+                                  not in the qualifs for that `const`"
+                                );
+                            }
+                        }
+                    }
+                }
+            } else if !self.saw_const_match_lint.get() {
+                match cv.ty().kind() {
+                    ty::RawPtr(pointee) if pointee.ty.is_sized(self.tcx(), self.param_env) => {}
+                    ty::FnPtr(..) | ty::RawPtr(..) => {
+                        self.tcx().emit_spanned_lint(
+                            lint::builtin::POINTER_STRUCTURAL_MATCH,
+                            self.id,
+                            self.span,
+                            PointerPattern,
+                        );
+                    }
+                    _ => {}
                 }
             }
         }
@@ -171,6 +243,7 @@ impl<'tcx> ConstToPat<'tcx> {
         inlined_const_as_pat
     }
 
+    #[instrument(level = "trace", skip(self), ret)]
     fn type_may_have_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool {
         // double-check there even *is* a semantic `PartialEq` to dispatch to.
         //
@@ -187,29 +260,19 @@ impl<'tcx> ConstToPat<'tcx> {
         );
 
         // FIXME: should this call a `predicate_must_hold` variant instead?
-        let has_impl = self.infcx.predicate_may_hold(&partial_eq_obligation);
-
-        // Note: To fix rust-lang/rust#65466, we could just remove this type
-        // walk hack for function pointers, and unconditionally error
-        // if `PartialEq` is not implemented. However, that breaks stable
-        // code at the moment, because types like `for <'a> fn(&'a ())` do
-        // not *yet* implement `PartialEq`. So for now we leave this here.
-        has_impl
-            || ty.walk().any(|t| match t.unpack() {
-                ty::subst::GenericArgKind::Lifetime(_) => false,
-                ty::subst::GenericArgKind::Type(t) => t.is_fn_ptr(),
-                ty::subst::GenericArgKind::Const(_) => false,
-            })
+        self.infcx.predicate_may_hold(&partial_eq_obligation)
     }
 
     fn field_pats(
         &self,
-        vals: impl Iterator<Item = mir::ConstantKind<'tcx>>,
+        vals: impl Iterator<Item = (ValTree<'tcx>, Ty<'tcx>)>,
     ) -> Result<Vec<FieldPat<'tcx>>, FallbackToConstRef> {
         vals.enumerate()
-            .map(|(idx, val)| {
+            .map(|(idx, (val, ty))| {
                 let field = FieldIdx::new(idx);
-                Ok(FieldPat { field, pattern: self.recur(val, false)? })
+                // Patterns can only use monomorphic types.
+                let ty = self.tcx().normalize_erasing_regions(self.param_env, ty);
+                Ok(FieldPat { field, pattern: self.recur(val, ty, false)? })
             })
             .collect()
     }
@@ -218,7 +281,8 @@ impl<'tcx> ConstToPat<'tcx> {
     #[instrument(skip(self), level = "debug")]
     fn recur(
         &self,
-        cv: mir::ConstantKind<'tcx>,
+        cv: ValTree<'tcx>,
+        ty: Ty<'tcx>,
         mir_structural_match_violation: bool,
     ) -> Result<Box<Pat<'tcx>>, FallbackToConstRef> {
         let id = self.id;
@@ -226,8 +290,9 @@ impl<'tcx> ConstToPat<'tcx> {
         let tcx = self.tcx();
         let param_env = self.param_env;
 
-        let kind = match cv.ty().kind() {
+        let kind = match ty.kind() {
             ty::Float(_) => {
+                self.saw_const_match_lint.set(true);
                 tcx.emit_spanned_lint(
                     lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
                     id,
@@ -236,27 +301,6 @@ impl<'tcx> ConstToPat<'tcx> {
                 );
                 return Err(FallbackToConstRef);
             }
-            ty::Adt(adt_def, _) if adt_def.is_union() => {
-                // Matching on union fields is unsafe, we can't hide it in constants
-                self.saw_const_match_error.set(true);
-                let err = UnionPattern { span };
-                tcx.sess.emit_err(err);
-                PatKind::Wild
-            }
-            ty::Adt(..)
-                if !self.type_may_have_partial_eq_impl(cv.ty())
-                    // FIXME(#73448): Find a way to bring const qualification into parity with
-                    // `search_for_structural_match_violation` and then remove this condition.
-
-                    // Obtain the actual type that isn't annotated. If we just looked at `cv.ty` we
-                    // could get `Option<NonStructEq>`, even though `Option` is annotated with derive.
-                    && let Some(non_sm_ty) = traits::search_for_structural_match_violation(span, tcx, cv.ty()) =>
-            {
-                self.saw_const_match_error.set(true);
-                let err = TypeNotStructural { span, non_sm_ty };
-                tcx.sess.emit_err(err);
-                PatKind::Wild
-            }
             // If the type is not structurally comparable, just emit the constant directly,
             // causing the pattern match code to treat it opaquely.
             // FIXME: This code doesn't emit errors itself, the caller emits the errors.
@@ -266,16 +310,14 @@ impl<'tcx> ConstToPat<'tcx> {
             // details.
             // Backwards compatibility hack because we can't cause hard errors on these
             // types, so we compare them via `PartialEq::eq` at runtime.
-            ty::Adt(..) if !self.type_marked_structural(cv.ty()) && self.behind_reference.get() => {
-                if !self.saw_const_match_error.get()
-                    && !self.saw_const_match_lint.get()
-                {
+            ty::Adt(..) if !self.type_marked_structural(ty) && self.behind_reference.get() => {
+                if !self.saw_const_match_error.get() && !self.saw_const_match_lint.get() {
                     self.saw_const_match_lint.set(true);
                     tcx.emit_spanned_lint(
                         lint::builtin::INDIRECT_STRUCTURAL_MATCH,
                         id,
                         span,
-                        IndirectStructuralMatch { non_sm_ty: cv.ty() },
+                        IndirectStructuralMatch { non_sm_ty: ty },
                     );
                 }
                 // Since we are behind a reference, we can just bubble the error up so we get a
@@ -283,77 +325,75 @@ impl<'tcx> ConstToPat<'tcx> {
                 // `PartialEq::eq` on it.
                 return Err(FallbackToConstRef);
             }
-            ty::Adt(adt_def, _) if !self.type_marked_structural(cv.ty()) => {
-                debug!(
-                    "adt_def {:?} has !type_marked_structural for cv.ty: {:?}",
-                    adt_def,
-                    cv.ty()
-                );
+            ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => {
+                debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty,);
                 self.saw_const_match_error.set(true);
-                let err = TypeNotStructural { span, non_sm_ty: cv.ty() };
+                let err = TypeNotStructural { span, non_sm_ty: ty };
                 tcx.sess.emit_err(err);
                 PatKind::Wild
             }
             ty::Adt(adt_def, substs) if adt_def.is_enum() => {
-                let destructured = tcx.destructure_mir_constant(param_env, cv);
-
+                let (&variant_index, fields) = cv.unwrap_branch().split_first().unwrap();
+                let variant_index =
+                    VariantIdx::from_u32(variant_index.unwrap_leaf().try_to_u32().ok().unwrap());
                 PatKind::Variant {
                     adt_def: *adt_def,
                     substs,
-                    variant_index: destructured
-                        .variant
-                        .expect("destructed const of adt without variant id"),
-                    subpatterns: self.field_pats(destructured.fields.iter().copied())?,
+                    variant_index,
+                    subpatterns: self.field_pats(
+                        fields.iter().copied().zip(
+                            adt_def.variants()[variant_index]
+                                .fields
+                                .iter()
+                                .map(|field| field.ty(self.tcx(), substs)),
+                        ),
+                    )?,
                 }
             }
-            ty::Tuple(_) | ty::Adt(_, _) => {
-                let destructured = tcx.destructure_mir_constant(param_env, cv);
-                PatKind::Leaf { subpatterns: self.field_pats(destructured.fields.iter().copied())? }
-            }
-            ty::Array(..) => PatKind::Array {
-                prefix: tcx
-                    .destructure_mir_constant(param_env, cv)
-                    .fields
+            ty::Tuple(fields) => PatKind::Leaf {
+                subpatterns: self
+                    .field_pats(cv.unwrap_branch().iter().copied().zip(fields.iter()))?,
+            },
+            ty::Adt(def, substs) => PatKind::Leaf {
+                subpatterns: self.field_pats(cv.unwrap_branch().iter().copied().zip(
+                    def.non_enum_variant().fields.iter().map(|field| field.ty(self.tcx(), substs)),
+                ))?,
+            },
+            ty::Array(elem_ty, _) => PatKind::Array {
+                prefix: cv
+                    .unwrap_branch()
                     .iter()
-                    .map(|val| self.recur(*val, false))
+                    .map(|val| self.recur(*val, *elem_ty, false))
                     .collect::<Result<_, _>>()?,
                 slice: None,
                 suffix: Box::new([]),
             },
             ty::Ref(_, pointee_ty, ..) => match *pointee_ty.kind() {
-                // These are not allowed and will error elsewhere anyway.
-                ty::Dynamic(..) => {
-                    self.saw_const_match_error.set(true);
-                    let err = InvalidPattern { span, non_sm_ty: cv.ty() };
-                    tcx.sess.emit_err(err);
-                    PatKind::Wild
-                }
-                // `&str` is represented as `ConstValue::Slice`, let's keep using this
+                // `&str` is represented as a valtree, let's keep using this
                 // optimization for now.
-                ty::Str => PatKind::Constant { value: cv },
+                ty::Str => PatKind::Constant { value: mir::ConstantKind::Ty(tcx.mk_const(cv, ty)) },
                 // `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when
                 // matching against references, you can only use byte string literals.
                 // The typechecker has a special case for byte string literals, by treating them
                 // as slices. This means we turn `&[T; N]` constants into slice patterns, which
                 // has no negative effects on pattern matching, even if we're actually matching on
                 // arrays.
-                ty::Array(..) if !self.treat_byte_string_as_slice => {
+                ty::Array(elem_ty, _) if !self.treat_byte_string_as_slice => {
                     let old = self.behind_reference.replace(true);
-                    let array = tcx.deref_mir_constant(self.param_env.and(cv));
+                    // References have the same valtree representation as their pointee.
+                    let array = cv;
                     let val = PatKind::Deref {
                         subpattern: Box::new(Pat {
                             kind: PatKind::Array {
-                                prefix: tcx
-                                    .destructure_mir_constant(param_env, array)
-                                    .fields
+                                prefix: array.unwrap_branch()
                                     .iter()
-                                    .map(|val| self.recur(*val, false))
+                                    .map(|val| self.recur(*val, elem_ty, false))
                                     .collect::<Result<_, _>>()?,
                                 slice: None,
                                 suffix: Box::new([]),
                             },
                             span,
-                            ty: *pointee_ty,
+                            ty: tcx.mk_slice(elem_ty),
                         }),
                     };
                     self.behind_reference.set(old);
@@ -365,15 +405,14 @@ impl<'tcx> ConstToPat<'tcx> {
                 // pattern.
                 ty::Slice(elem_ty) => {
                     let old = self.behind_reference.replace(true);
-                    let array = tcx.deref_mir_constant(self.param_env.and(cv));
+                    // References have the same valtree representation as their pointee.
+                    let array = cv;
                     let val = PatKind::Deref {
                         subpattern: Box::new(Pat {
                             kind: PatKind::Slice {
-                                prefix: tcx
-                                    .destructure_mir_constant(param_env, array)
-                                    .fields
+                                prefix: array.unwrap_branch()
                                     .iter()
-                                    .map(|val| self.recur(*val, false))
+                                    .map(|val| self.recur(*val, elem_ty, false))
                                     .collect::<Result<_, _>>()?,
                                 slice: None,
                                 suffix: Box::new([]),
@@ -418,48 +457,28 @@ impl<'tcx> ConstToPat<'tcx> {
                 // deref pattern.
                 _ => {
                     if !pointee_ty.is_sized(tcx, param_env) {
-                        // `tcx.deref_mir_constant()` below will ICE with an unsized type
-                        // (except slices, which are handled in a separate arm above).
-
                         let err = UnsizedPattern { span, non_sm_ty: *pointee_ty };
                         tcx.sess.emit_err(err);
 
+                        // FIXME: introduce PatKind::Error to silence follow up diagnostics due to unreachable patterns.
                         PatKind::Wild
                     } else {
                         let old = self.behind_reference.replace(true);
-                        let subpattern = self.recur(tcx.deref_mir_constant(self.param_env.and(cv)), false)?;
+                        // References have the same valtree representation as their pointee.
+                        let subpattern = self.recur(cv, *pointee_ty, false)?;
                         self.behind_reference.set(old);
                         PatKind::Deref { subpattern }
                     }
                 }
             },
             ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::FnDef(..) => {
-                PatKind::Constant { value: cv }
-            }
-            ty::RawPtr(pointee) if pointee.ty.is_sized(tcx, param_env) => {
-                return Err(FallbackToConstRef);
-            }
-            // FIXME: these can have very surprising behaviour where optimization levels or other
-            // compilation choices change the runtime behaviour of the match.
-            // See https://github.com/rust-lang/rust/issues/70861 for examples.
-            ty::FnPtr(..) | ty::RawPtr(..) => {
-                if !self.saw_const_match_error.get()
-                    && !self.saw_const_match_lint.get()
-                {
-                    self.saw_const_match_lint.set(true);
-                    tcx.emit_spanned_lint(
-                        lint::builtin::POINTER_STRUCTURAL_MATCH,
-                        id,
-                        span,
-                        PointerPattern
-                    );
-                }
-                return Err(FallbackToConstRef);
+                PatKind::Constant { value: mir::ConstantKind::Ty(tcx.mk_const(cv, ty)) }
             }
+            ty::FnPtr(..) | ty::RawPtr(..) => unreachable!(),
             _ => {
                 self.saw_const_match_error.set(true);
-                let err = InvalidPattern { span, non_sm_ty: cv.ty() };
-                    tcx.sess.emit_err(err);
+                let err = InvalidPattern { span, non_sm_ty: ty };
+                tcx.sess.emit_err(err);
                 PatKind::Wild
             }
         };
@@ -472,7 +491,7 @@ impl<'tcx> ConstToPat<'tcx> {
 
             // Obtain the actual type that isn't annotated. If we just looked at `cv.ty` we
             // could get `Option<NonStructEq>`, even though `Option` is annotated with derive.
-            && let Some(non_sm_ty) = traits::search_for_structural_match_violation(span, tcx, cv.ty())
+            && let Some(non_sm_ty) = traits::search_for_structural_match_violation(span, tcx, ty)
         {
             self.saw_const_match_lint.set(true);
             tcx.emit_spanned_lint(
@@ -483,6 +502,6 @@ impl<'tcx> ConstToPat<'tcx> {
             );
         }
 
-        Ok(Box::new(Pat { span, ty: cv.ty(), kind }))
+        Ok(Box::new(Pat { span, ty, kind }))
     }
 }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
index 6a77146138b..9df6d2f43ad 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
@@ -53,11 +53,11 @@ use smallvec::{smallvec, SmallVec};
 use rustc_data_structures::captures::Captures;
 use rustc_hir::{HirId, RangeEnd};
 use rustc_index::Idx;
+use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::mir;
 use rustc_middle::thir::{FieldPat, Pat, PatKind, PatRange};
 use rustc_middle::ty::layout::IntegerExt;
 use rustc_middle::ty::{self, Ty, TyCtxt, VariantDef};
-use rustc_middle::{middle::stability::EvalResult, mir::interpret::ConstValue};
 use rustc_session::lint;
 use rustc_span::{Span, DUMMY_SP};
 use rustc_target::abi::{FieldIdx, Integer, Size, VariantIdx, FIRST_VARIANT};
@@ -140,28 +140,17 @@ impl IntRange {
         value: mir::ConstantKind<'tcx>,
     ) -> Option<IntRange> {
         let ty = value.ty();
-        if let Some((target_size, bias)) = Self::integral_size_and_signed_bias(tcx, ty) {
-            let val = if let mir::ConstantKind::Val(ConstValue::Scalar(scalar), _) = value {
-                // For this specific pattern we can skip a lot of effort and go
-                // straight to the result, after doing a bit of checking. (We
-                // could remove this branch and just fall through, which
-                // is more general but much slower.)
-                scalar.to_bits_or_ptr_internal(target_size).unwrap().left()?
-            } else {
-                if let mir::ConstantKind::Ty(c) = value
-                    && let ty::ConstKind::Value(_) = c.kind()
-                {
-                    bug!("encountered ConstValue in mir::ConstantKind::Ty, whereas this is expected to be in ConstantKind::Val");
-                }
+        let (target_size, bias) = Self::integral_size_and_signed_bias(tcx, ty)?;
+        let val = match value {
+            mir::ConstantKind::Ty(c) if let ty::ConstKind::Value(valtree) = c.kind() => {
+                valtree.unwrap_leaf().to_bits(target_size).ok()
+            },
+            // This is a more general form of the previous case.
+            _ => value.try_eval_bits(tcx, param_env, ty),
+        }?;
 
-                // This is a more general form of the previous case.
-                value.try_eval_bits(tcx, param_env, ty)?
-            };
-            let val = val ^ bias;
-            Some(IntRange { range: val..=val, bias })
-        } else {
-            None
-        }
+        let val = val ^ bias;
+        Some(IntRange { range: val..=val, bias })
     }
 
     #[inline]
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 1cf2f7ec0ff..1bbe7b45c1e 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -18,14 +18,15 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator;
 use rustc_hir::RangeEnd;
 use rustc_index::Idx;
 use rustc_middle::mir::interpret::{
-    ConstValue, ErrorHandled, LitToConstError, LitToConstInput, Scalar,
+    ConstValue, ErrorHandled, GlobalId, LitToConstError, LitToConstInput, Scalar,
 };
-use rustc_middle::mir::{self, UserTypeProjection};
+use rustc_middle::mir::{self, ConstantKind, UserTypeProjection};
 use rustc_middle::mir::{BorrowKind, Mutability};
 use rustc_middle::thir::{Ascription, BindingMode, FieldPat, LocalVarId, Pat, PatKind, PatRange};
 use rustc_middle::ty::subst::{GenericArg, SubstsRef};
 use rustc_middle::ty::CanonicalUserTypeAnnotation;
-use rustc_middle::ty::{self, AdtDef, ConstKind, Region, Ty, TyCtxt, UserType};
+use rustc_middle::ty::TypeVisitableExt;
+use rustc_middle::ty::{self, AdtDef, Region, Ty, TyCtxt, UserType};
 use rustc_span::{Span, Symbol};
 use rustc_target::abi::FieldIdx;
 
@@ -518,16 +519,24 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             }
         };
 
-        // `mir_const_qualif` must be called with the `DefId` of the item where the const is
-        // defined, not where it is declared. The difference is significant for associated
-        // constants.
-        let mir_structural_match_violation = self.tcx.mir_const_qualif(instance.def_id()).custom_eq;
-        debug!("mir_structural_match_violation({:?}) -> {}", qpath, mir_structural_match_violation);
-
-        match self.tcx.const_eval_instance(param_env_reveal_all, instance, Some(span)) {
-            Ok(literal) => {
-                let const_ = mir::ConstantKind::Val(literal, ty);
-                let pattern = self.const_to_pat(const_, id, span, mir_structural_match_violation);
+        let cid = GlobalId { instance, promoted: None };
+        // Prefer valtrees over opaque constants.
+        let const_value = self
+            .tcx
+            .const_eval_global_id_for_typeck(param_env_reveal_all, cid, Some(span))
+            .map(|val| match val {
+                Some(valtree) => mir::ConstantKind::Ty(self.tcx.mk_const(valtree, ty)),
+                None => mir::ConstantKind::Val(
+                    self.tcx
+                        .const_eval_global_id(param_env_reveal_all, cid, Some(span))
+                        .expect("const_eval_global_id_for_typeck should have already failed"),
+                    ty,
+                ),
+            });
+
+        match const_value {
+            Ok(const_) => {
+                let pattern = self.const_to_pat(const_, id, span, Some(instance.def_id()));
 
                 if !is_associated_const {
                     return pattern;
@@ -577,27 +586,69 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         id: hir::HirId,
         span: Span,
     ) -> PatKind<'tcx> {
-        let value = mir::ConstantKind::from_inline_const(self.tcx, anon_const.def_id);
-
-        // Evaluate early like we do in `lower_path`.
-        let value = value.eval(self.tcx, self.param_env);
-
-        match value {
-            mir::ConstantKind::Ty(c) => match c.kind() {
-                ConstKind::Param(_) => {
-                    self.tcx.sess.emit_err(ConstParamInPattern { span });
-                    return PatKind::Wild;
-                }
-                ConstKind::Error(_) => {
-                    return PatKind::Wild;
+        let tcx = self.tcx;
+        let def_id = anon_const.def_id;
+        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+        let body_id = match tcx.hir().get(hir_id) {
+            hir::Node::AnonConst(ac) => ac.body,
+            _ => span_bug!(
+                tcx.def_span(def_id.to_def_id()),
+                "from_inline_const can only process anonymous constants"
+            ),
+        };
+        let expr = &tcx.hir().body(body_id).value;
+        let ty = tcx.typeck(def_id).node_type(hir_id);
+
+        // Special case inline consts that are just literals. This is solely
+        // a performance optimization, as we could also just go through the regular
+        // const eval path below.
+        // FIXME: investigate the performance impact of removing this.
+        let lit_input = match expr.kind {
+            hir::ExprKind::Lit(ref lit) => Some(LitToConstInput { lit: &lit.node, ty, neg: false }),
+            hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => match expr.kind {
+                hir::ExprKind::Lit(ref lit) => {
+                    Some(LitToConstInput { lit: &lit.node, ty, neg: true })
                 }
-                _ => bug!("Expected ConstKind::Param"),
+                _ => None,
             },
-            mir::ConstantKind::Val(_, _) => self.const_to_pat(value, id, span, false).kind,
-            mir::ConstantKind::Unevaluated(..) => {
-                // If we land here it means the const can't be evaluated because it's `TooGeneric`.
-                self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span });
-                return PatKind::Wild;
+            _ => None,
+        };
+        if let Some(lit_input) = lit_input {
+            match tcx.at(expr.span).lit_to_const(lit_input) {
+                Ok(c) => return self.const_to_pat(ConstantKind::Ty(c), id, span, None).kind,
+                // If an error occurred, ignore that it's a literal
+                // and leave reporting the error up to const eval of
+                // the unevaluated constant below.
+                Err(_) => {}
+            }
+        }
+
+        let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id());
+        let parent_substs =
+            tcx.erase_regions(ty::InternalSubsts::identity_for_item(tcx, typeck_root_def_id));
+        let substs =
+            ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
+                .substs;
+
+        let uneval = mir::UnevaluatedConst { def: def_id.to_def_id(), substs, promoted: None };
+        debug_assert!(!substs.has_free_regions());
+
+        let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), substs: substs };
+        // First try using a valtree in order to destructure the constant into a pattern.
+        if let Ok(Some(valtree)) =
+            self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, Some(span))
+        {
+            self.const_to_pat(ConstantKind::Ty(self.tcx.mk_const(valtree, ty)), id, span, None).kind
+        } else {
+            // If that fails, convert it to an opaque constant pattern.
+            match tcx.const_eval_resolve(self.param_env, uneval, None) {
+                Ok(val) => self.const_to_pat(mir::ConstantKind::Val(val, ty), id, span, None).kind,
+                Err(ErrorHandled::TooGeneric) => {
+                    // If we land here it means the const can't be evaluated because it's `TooGeneric`.
+                    self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span });
+                    PatKind::Wild
+                }
+                Err(ErrorHandled::Reported(_)) => PatKind::Wild,
             }
         }
     }
@@ -626,8 +677,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
 
         let lit_input =
             LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
-        match self.tcx.at(expr.span).lit_to_mir_constant(lit_input) {
-            Ok(constant) => self.const_to_pat(constant, expr.hir_id, lit.span, false).kind,
+        match self.tcx.at(expr.span).lit_to_const(lit_input) {
+            Ok(constant) => {
+                self.const_to_pat(ConstantKind::Ty(constant), expr.hir_id, lit.span, None).kind
+            }
             Err(LitToConstError::Reported(_)) => PatKind::Wild,
             Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
         }
@@ -806,6 +859,9 @@ pub(crate) fn compare_const_vals<'tcx>(
                 mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(a)), _a_ty),
                 mir::ConstantKind::Val(ConstValue::Scalar(Scalar::Int(b)), _b_ty),
             ) => return Some(a.cmp(&b)),
+            (mir::ConstantKind::Ty(a), mir::ConstantKind::Ty(b)) => {
+                return Some(a.kind().cmp(&b.kind()));
+            }
             _ => {}
         },
     }
diff --git a/compiler/rustc_mir_transform/src/const_goto.rs b/compiler/rustc_mir_transform/src/const_goto.rs
index da101ca7ad2..024bea62098 100644
--- a/compiler/rustc_mir_transform/src/const_goto.rs
+++ b/compiler/rustc_mir_transform/src/const_goto.rs
@@ -28,7 +28,7 @@ pub struct ConstGoto;
 
 impl<'tcx> MirPass<'tcx> for ConstGoto {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
-        sess.mir_opt_level() >= 4
+        sess.mir_opt_level() >= 2
     }
 
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index 1ba1951afde..1d43dbda0aa 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -4,6 +4,7 @@
 use either::Right;
 
 use rustc_const_eval::const_eval::CheckAlignment;
+use rustc_const_eval::ReportErrorExt;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::DefKind;
 use rustc_index::bit_set::BitSet;
@@ -37,6 +38,7 @@ macro_rules! throw_machine_stop_str {
     ($($tt:tt)*) => {{
         // We make a new local type for it. The type itself does not carry any information,
         // but its vtable (for the `MachineStopType` trait) does.
+        #[derive(Debug)]
         struct Zst;
         // Printing this type shows the desired string.
         impl std::fmt::Display for Zst {
@@ -44,7 +46,17 @@ macro_rules! throw_machine_stop_str {
                 write!(f, $($tt)*)
             }
         }
-        impl rustc_middle::mir::interpret::MachineStopType for Zst {}
+
+        impl rustc_middle::mir::interpret::MachineStopType for Zst {
+            fn diagnostic_message(&self) -> rustc_errors::DiagnosticMessage {
+                self.to_string().into()
+            }
+
+            fn add_args(
+                self: Box<Self>,
+                _: &mut dyn FnMut(std::borrow::Cow<'static, str>, rustc_errors::DiagnosticArgValue<'static>),
+            ) {}
+        }
         throw_machine_stop!(Zst)
     }};
 }
@@ -103,7 +115,14 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
         // That would require a uniform one-def no-mutation analysis
         // and RPO (or recursing when needing the value of a local).
         let mut optimization_finder = ConstPropagator::new(body, dummy_body, tcx);
-        optimization_finder.visit_body(body);
+
+        // Traverse the body in reverse post-order, to ensure that `FullConstProp` locals are
+        // assigned before being read.
+        let postorder = body.basic_blocks.postorder().to_vec();
+        for bb in postorder.into_iter().rev() {
+            let data = &mut body.basic_blocks.as_mut_preserves_cfg()[bb];
+            optimization_finder.visit_basic_block_data(bb, data);
+        }
 
         trace!("ConstProp done for {:?}", def_id);
     }
@@ -367,7 +386,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                 op
             }
             Err(e) => {
-                trace!("get_const failed: {}", e);
+                trace!("get_const failed: {:?}", e.into_kind().debug());
                 return None;
             }
         };
@@ -789,12 +808,6 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
         self.tcx
     }
 
-    fn visit_body(&mut self, body: &mut Body<'tcx>) {
-        for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
-            self.visit_basic_block_data(bb, data);
-        }
-    }
-
     fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) {
         self.super_operand(operand, location);
 
@@ -885,14 +898,23 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
                 }
             }
             StatementKind::StorageLive(local) => {
-                let frame = self.ecx.frame_mut();
-                frame.locals[local].value =
-                    LocalValue::Live(interpret::Operand::Immediate(interpret::Immediate::Uninit));
-            }
-            StatementKind::StorageDead(local) => {
-                let frame = self.ecx.frame_mut();
-                frame.locals[local].value = LocalValue::Dead;
+                Self::remove_const(&mut self.ecx, local);
             }
+            // We do not need to mark dead locals as such. For `FullConstProp` locals,
+            // this allows to propagate the single assigned value in this case:
+            // ```
+            // let x = SOME_CONST;
+            // if a {
+            //   f(copy x);
+            //   StorageDead(x);
+            // } else {
+            //   g(copy x);
+            //   StorageDead(x);
+            // }
+            // ```
+            //
+            // This may propagate a constant where the local would be uninit or dead.
+            // In both cases, this does not matter, as those reads would be UB anyway.
             _ => {}
         }
     }
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index 0fe49b8a1bb..759650fe4db 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -9,6 +9,7 @@ use rustc_const_eval::interpret::Immediate;
 use rustc_const_eval::interpret::{
     self, InterpCx, InterpResult, LocalValue, MemoryKind, OpTy, Scalar, StackPopCleanup,
 };
+use rustc_const_eval::ReportErrorExt;
 use rustc_hir::def::DefKind;
 use rustc_hir::HirId;
 use rustc_index::bit_set::BitSet;
@@ -232,7 +233,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                 op
             }
             Err(e) => {
-                trace!("get_const failed: {}", e);
+                trace!("get_const failed: {:?}", e.into_kind().debug());
                 return None;
             }
         };
@@ -272,8 +273,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                 // dedicated error variants should be introduced instead.
                 assert!(
                     !error.kind().formatted_string(),
-                    "const-prop encountered formatting error: {}",
-                    error
+                    "const-prop encountered formatting error: {error:?}",
                 );
                 None
             }
diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs
index 602e40d5131..22f71bb0851 100644
--- a/compiler/rustc_mir_transform/src/errors.rs
+++ b/compiler/rustc_mir_transform/src/errors.rs
@@ -163,7 +163,14 @@ impl<'a, P: std::fmt::Debug> DecorateLint<'a, ()> for AssertLint<P> {
         self,
         diag: &'b mut DiagnosticBuilder<'a, ()>,
     ) -> &'b mut DiagnosticBuilder<'a, ()> {
-        diag.span_label(self.span(), format!("{:?}", self.panic()));
+        let span = self.span();
+        let assert_kind = self.panic();
+        let message = assert_kind.diagnostic_message();
+        assert_kind.add_args(&mut |name, value| {
+            diag.set_arg(name, value);
+        });
+        diag.span_label(span, message);
+
         diag
     }
 
@@ -191,7 +198,7 @@ impl<P> AssertLint<P> {
             AssertLint::ArithmeticOverflow(sp, _) | AssertLint::UnconditionalPanic(sp, _) => *sp,
         }
     }
-    pub fn panic(&self) -> &AssertKind<P> {
+    pub fn panic(self) -> AssertKind<P> {
         match self {
             AssertLint::ArithmeticOverflow(_, p) | AssertLint::UnconditionalPanic(_, p) => p,
         }
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 54c138b6fbd..7d9f6c38e36 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -559,10 +559,13 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
             // inst combine is after MatchBranchSimplification to clean up Ne(_1, false)
             &multiple_return_terminators::MultipleReturnTerminators,
             &instsimplify::InstSimplify,
-            &separate_const_switch::SeparateConstSwitch,
             &simplify::SimplifyLocals::BeforeConstProp,
             &copy_prop::CopyProp,
             &ref_prop::ReferencePropagation,
+            // Perform `SeparateConstSwitch` after SSA-based analyses, as cloning blocks may
+            // destroy the SSA property. It should still happen before const-propagation, so the
+            // latter pass will leverage the created opportunities.
+            &separate_const_switch::SeparateConstSwitch,
             &const_prop::ConstProp,
             &dataflow_const_prop::DataflowConstProp,
             //
diff --git a/compiler/rustc_mir_transform/src/required_consts.rs b/compiler/rustc_mir_transform/src/required_consts.rs
index 0ea8f2ba93f..243cb463560 100644
--- a/compiler/rustc_mir_transform/src/required_consts.rs
+++ b/compiler/rustc_mir_transform/src/required_consts.rs
@@ -17,8 +17,8 @@ impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> {
         let literal = constant.literal;
         match literal {
             ConstantKind::Ty(c) => match c.kind() {
-                ConstKind::Param(_) | ConstKind::Error(_) => {}
-                _ => bug!("only ConstKind::Param should be encountered here, got {:#?}", c),
+                ConstKind::Param(_) | ConstKind::Error(_) | ConstKind::Value(_) => {}
+                _ => bug!("only ConstKind::Param/Value should be encountered here, got {:#?}", c),
             },
             ConstantKind::Unevaluated(..) => self.required_consts.push(*constant),
             ConstantKind::Val(..) => {}
diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs
index 2479856b727..f35a5fb4276 100644
--- a/compiler/rustc_mir_transform/src/separate_const_switch.rs
+++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs
@@ -46,7 +46,7 @@ pub struct SeparateConstSwitch;
 
 impl<'tcx> MirPass<'tcx> for SeparateConstSwitch {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
-        sess.mir_opt_level() >= 4
+        sess.mir_opt_level() >= 2
     }
 
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs
index 2d77291293d..e4b3b8b9262 100644
--- a/compiler/rustc_mir_transform/src/sroa.rs
+++ b/compiler/rustc_mir_transform/src/sroa.rs
@@ -6,23 +6,29 @@ use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_mir_dataflow::value_analysis::{excluded_locals, iter_fields};
-use rustc_target::abi::FieldIdx;
+use rustc_target::abi::{FieldIdx, ReprFlags, FIRST_VARIANT};
 
 pub struct ScalarReplacementOfAggregates;
 
 impl<'tcx> MirPass<'tcx> for ScalarReplacementOfAggregates {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
-        sess.mir_opt_level() >= 3
+        sess.mir_opt_level() >= 2
     }
 
     #[instrument(level = "debug", skip(self, tcx, body))]
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         debug!(def_id = ?body.source.def_id());
+
+        // Avoid query cycles (generators require optimized MIR for layout).
+        if tcx.type_of(body.source.def_id()).subst_identity().is_generator() {
+            return;
+        }
+
         let mut excluded = excluded_locals(body);
         let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id());
         loop {
             debug!(?excluded);
-            let escaping = escaping_locals(&excluded, body);
+            let escaping = escaping_locals(tcx, param_env, &excluded, body);
             debug!(?escaping);
             let replacements = compute_flattening(tcx, param_env, body, escaping);
             debug!(?replacements);
@@ -48,11 +54,45 @@ impl<'tcx> MirPass<'tcx> for ScalarReplacementOfAggregates {
 /// - the locals is a union or an enum;
 /// - the local's address is taken, and thus the relative addresses of the fields are observable to
 ///   client code.
-fn escaping_locals(excluded: &BitSet<Local>, body: &Body<'_>) -> BitSet<Local> {
+fn escaping_locals<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    excluded: &BitSet<Local>,
+    body: &Body<'tcx>,
+) -> BitSet<Local> {
+    let is_excluded_ty = |ty: Ty<'tcx>| {
+        if ty.is_union() || ty.is_enum() {
+            return true;
+        }
+        if let ty::Adt(def, _substs) = ty.kind() {
+            if def.repr().flags.contains(ReprFlags::IS_SIMD) {
+                // Exclude #[repr(simd)] types so that they are not de-optimized into an array
+                return true;
+            }
+            // We already excluded unions and enums, so this ADT must have one variant
+            let variant = def.variant(FIRST_VARIANT);
+            if variant.fields.len() > 1 {
+                // If this has more than one field, it cannot be a wrapper that only provides a
+                // niche, so we do not want to automatically exclude it.
+                return false;
+            }
+            let Ok(layout) = tcx.layout_of(param_env.and(ty)) else {
+                // We can't get the layout
+                return true;
+            };
+            if layout.layout.largest_niche().is_some() {
+                // This type has a niche
+                return true;
+            }
+        }
+        // Default for non-ADTs
+        false
+    };
+
     let mut set = BitSet::new_empty(body.local_decls.len());
     set.insert_range(RETURN_PLACE..=Local::from_usize(body.arg_count));
     for (local, decl) in body.local_decls().iter_enumerated() {
-        if decl.ty.is_union() || decl.ty.is_enum() || excluded.contains(local) {
+        if excluded.contains(local) || is_excluded_ty(decl.ty) {
             set.insert(local);
         }
     }
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index cefa64d27ac..09025c1ee33 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -179,7 +179,6 @@ use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
 use rustc_hir::lang_items::LangItem;
-use rustc_index::bit_set::GrowableBitSet;
 use rustc_middle::mir::interpret::{AllocId, ConstValue};
 use rustc_middle::mir::interpret::{ErrorHandled, GlobalAlloc, Scalar};
 use rustc_middle::mir::mono::{InstantiationMode, MonoItem};
@@ -220,78 +219,29 @@ pub struct InliningMap<'tcx> {
     // The range selects elements within the `targets` vecs.
     index: FxHashMap<MonoItem<'tcx>, Range<usize>>,
     targets: Vec<MonoItem<'tcx>>,
-
-    // Contains one bit per mono item in the `targets` field. That bit
-    // is true if that mono item needs to be inlined into every CGU.
-    inlines: GrowableBitSet<usize>,
-}
-
-/// Struct to store mono items in each collecting and if they should
-/// be inlined. We call `instantiation_mode` to get their inlining
-/// status when inserting new elements, which avoids calling it in
-/// `inlining_map.lock_mut()`. See the `collect_items_rec` implementation
-/// below.
-struct MonoItems<'tcx> {
-    // If this is false, we do not need to compute whether items
-    // will need to be inlined.
-    compute_inlining: bool,
-
-    // The TyCtxt used to determine whether the a item should
-    // be inlined.
-    tcx: TyCtxt<'tcx>,
-
-    // The collected mono items. The bool field in each element
-    // indicates whether this element should be inlined.
-    items: Vec<(Spanned<MonoItem<'tcx>>, bool /*inlined*/)>,
 }
 
-impl<'tcx> MonoItems<'tcx> {
-    #[inline]
-    fn push(&mut self, item: Spanned<MonoItem<'tcx>>) {
-        self.extend([item]);
-    }
-
-    #[inline]
-    fn extend<T: IntoIterator<Item = Spanned<MonoItem<'tcx>>>>(&mut self, iter: T) {
-        self.items.extend(iter.into_iter().map(|mono_item| {
-            let inlined = if !self.compute_inlining {
-                false
-            } else {
-                mono_item.node.instantiation_mode(self.tcx) == InstantiationMode::LocalCopy
-            };
-            (mono_item, inlined)
-        }))
-    }
-}
+type MonoItems<'tcx> = Vec<Spanned<MonoItem<'tcx>>>;
 
 impl<'tcx> InliningMap<'tcx> {
     fn new() -> InliningMap<'tcx> {
-        InliningMap {
-            index: FxHashMap::default(),
-            targets: Vec::new(),
-            inlines: GrowableBitSet::with_capacity(1024),
-        }
+        InliningMap { index: FxHashMap::default(), targets: Vec::new() }
     }
 
     fn record_accesses<'a>(
         &mut self,
         source: MonoItem<'tcx>,
-        new_targets: &'a [(Spanned<MonoItem<'tcx>>, bool)],
+        new_targets: &'a [Spanned<MonoItem<'tcx>>],
     ) where
         'tcx: 'a,
     {
         let start_index = self.targets.len();
         let new_items_count = new_targets.len();
-        let new_items_count_total = new_items_count + self.targets.len();
 
         self.targets.reserve(new_items_count);
-        self.inlines.ensure(new_items_count_total);
 
-        for (i, (Spanned { node: mono_item, .. }, inlined)) in new_targets.into_iter().enumerate() {
+        for Spanned { node: mono_item, .. } in new_targets.into_iter() {
             self.targets.push(*mono_item);
-            if *inlined {
-                self.inlines.insert(i + start_index);
-            }
         }
 
         let end_index = self.targets.len();
@@ -300,13 +250,14 @@ impl<'tcx> InliningMap<'tcx> {
 
     /// Internally iterate over all items referenced by `source` which will be
     /// made available for inlining.
-    pub fn with_inlining_candidates<F>(&self, source: MonoItem<'tcx>, mut f: F)
+    pub fn with_inlining_candidates<F>(&self, tcx: TyCtxt<'tcx>, source: MonoItem<'tcx>, mut f: F)
     where
         F: FnMut(MonoItem<'tcx>),
     {
         if let Some(range) = self.index.get(&source) {
-            for (i, candidate) in self.targets[range.clone()].iter().enumerate() {
-                if self.inlines.contains(range.start + i) {
+            for candidate in self.targets[range.clone()].iter() {
+                let is_inlined = candidate.instantiation_mode(tcx) == InstantiationMode::LocalCopy;
+                if is_inlined {
                     f(*candidate);
                 }
             }
@@ -367,7 +318,7 @@ pub fn collect_crate_mono_items(
 #[instrument(skip(tcx, mode), level = "debug")]
 fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<'_>> {
     debug!("collecting roots");
-    let mut roots = MonoItems { compute_inlining: false, tcx, items: Vec::new() };
+    let mut roots = Vec::new();
 
     {
         let entry_fn = tcx.entry_fn(());
@@ -393,9 +344,8 @@ fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionMode) -> Vec<MonoItem<
     // whose predicates hold. Luckily, items that aren't instantiable
     // can't actually be used, so we can just skip codegenning them.
     roots
-        .items
         .into_iter()
-        .filter_map(|(Spanned { node: mono_item, .. }, _)| {
+        .filter_map(|Spanned { node: mono_item, .. }| {
             mono_item.is_instantiable(tcx).then_some(mono_item)
         })
         .collect()
@@ -417,7 +367,7 @@ fn collect_items_rec<'tcx>(
         return;
     }
 
-    let mut neighbors = MonoItems { compute_inlining: true, tcx, items: Vec::new() };
+    let mut neighbors = Vec::new();
     let recursion_depth_reset;
 
     //
@@ -542,9 +492,9 @@ fn collect_items_rec<'tcx>(
             formatted_item,
         });
     }
-    inlining_map.lock_mut().record_accesses(starting_point.node, &neighbors.items);
+    inlining_map.lock_mut().record_accesses(starting_point.node, &neighbors);
 
-    for (neighbour, _) in neighbors.items {
+    for neighbour in neighbors {
         collect_items_rec(tcx, neighbour, visited, recursion_depths, recursion_limit, inlining_map);
     }
 
diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs
index 1b872484eb1..015361f8ad5 100644
--- a/compiler/rustc_monomorphize/src/partitioning.rs
+++ b/compiler/rustc_monomorphize/src/partitioning.rs
@@ -426,7 +426,7 @@ fn place_inlined_mono_items<'tcx>(
         // Collect all items that need to be available in this codegen unit.
         let mut reachable = FxHashSet::default();
         for root in old_codegen_unit.items().keys() {
-            follow_inlining(*root, cx.inlining_map, &mut reachable);
+            follow_inlining(cx.tcx, *root, cx.inlining_map, &mut reachable);
         }
 
         let mut new_codegen_unit = CodegenUnit::new(old_codegen_unit.name());
@@ -480,6 +480,7 @@ fn place_inlined_mono_items<'tcx>(
     return mono_item_placements;
 
     fn follow_inlining<'tcx>(
+        tcx: TyCtxt<'tcx>,
         mono_item: MonoItem<'tcx>,
         inlining_map: &InliningMap<'tcx>,
         visited: &mut FxHashSet<MonoItem<'tcx>>,
@@ -488,8 +489,8 @@ fn place_inlined_mono_items<'tcx>(
             return;
         }
 
-        inlining_map.with_inlining_candidates(mono_item, |target| {
-            follow_inlining(target, inlining_map, visited);
+        inlining_map.with_inlining_candidates(tcx, mono_item, |target| {
+            follow_inlining(tcx, target, inlining_map, visited);
         });
     }
 }
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index 5a1ae808e66..9971bdf45bb 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -93,7 +93,7 @@ fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
 
         Err(layout_error) => {
             tcx.sess.emit_fatal(Spanned {
-                node: layout_error,
+                node: layout_error.into_diagnostic(),
                 span: tcx.def_span(item_def_id.to_def_id()),
             });
         }
@@ -109,12 +109,7 @@ impl<'tcx> LayoutOfHelpers<'tcx> for UnwrapLayoutCx<'tcx> {
     type LayoutOfResult = TyAndLayout<'tcx>;
 
     fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
-        span_bug!(
-            span,
-            "`#[rustc_layout(..)]` test resulted in `layout_of({}) = Err({})`",
-            ty,
-            err
-        );
+        span_bug!(span, "`#[rustc_layout(..)]` test resulted in `layout_of({ty}) = Err({err})`",);
     }
 }
 
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index d1e4042e8d8..a433e2371c9 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -84,6 +84,7 @@ impl SymbolGallery {
 
 /// Construct a diagnostic for a language feature error due to the given `span`.
 /// The `feature`'s `Symbol` is the one you used in `active.rs` and `rustc_span::symbols`.
+#[track_caller]
 pub fn feature_err(
     sess: &ParseSess,
     feature: Symbol,
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 1eb54cee5a1..2ebd83540ee 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -128,8 +128,6 @@ pub struct Limits {
     pub move_size_limit: Limit,
     /// The maximum length of types during monomorphization.
     pub type_length_limit: Limit,
-    /// The maximum blocks a const expression can evaluate.
-    pub const_eval_limit: Limit,
 }
 
 pub struct CompilerIO {
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index b219fde4da9..0c7e36b3bef 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -1288,7 +1288,7 @@ pub fn decode_expn_id(
     decode_data: impl FnOnce(ExpnId) -> (ExpnData, ExpnHash),
 ) -> ExpnId {
     if index == 0 {
-        debug!("decode_expn_id: deserialized root");
+        trace!("decode_expn_id: deserialized root");
         return ExpnId::root();
     }
 
@@ -1321,7 +1321,7 @@ pub fn decode_syntax_context<D: Decoder, F: FnOnce(&mut D, u32) -> SyntaxContext
 ) -> SyntaxContext {
     let raw_id: u32 = Decodable::decode(d);
     if raw_id == 0 {
-        debug!("decode_syntax_context: deserialized root");
+        trace!("decode_syntax_context: deserialized root");
         // The root is special
         return SyntaxContext::root();
     }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 1185563ea80..2f002e42427 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1146,6 +1146,8 @@ symbols! {
         profiler_builtins,
         profiler_runtime,
         ptr,
+        ptr_cast_mut,
+        ptr_from_ref,
         ptr_guaranteed_cmp,
         ptr_mask,
         ptr_null,
diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
index b245742e533..a1cb317c50e 100644
--- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs
@@ -501,7 +501,15 @@ fn encode_ty<'tcx>(
         ty::Array(ty0, len) => {
             // A<array-length><element-type>
             let mut s = String::from("A");
-            let _ = write!(s, "{}", &len.kind().try_to_scalar().unwrap().to_u64().unwrap());
+            let _ = write!(
+                s,
+                "{}",
+                &len.kind()
+                    .try_to_scalar()
+                    .unwrap()
+                    .to_u64()
+                    .unwrap_or_else(|_| panic!("failed to convert length to u64"))
+            );
             s.push_str(&encode_ty(tcx, *ty0, dict, options));
             compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
             typeid.push_str(&s);
@@ -786,7 +794,12 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio
         }
 
         ty::Array(ty0, len) => {
-            let len = len.kind().try_to_scalar().unwrap().to_u64().unwrap();
+            let len = len
+                .kind()
+                .try_to_scalar()
+                .unwrap()
+                .to_u64()
+                .unwrap_or_else(|_| panic!("failed to convert length to u64"));
             ty = tcx.mk_array(transform_ty(tcx, *ty0, options), len);
         }
 
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 1ae11f5671c..c4abf6f4b5e 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -2,7 +2,6 @@ use crate::abi::{self, Abi, Align, FieldsShape, Size};
 use crate::abi::{HasDataLayout, TyAbiInterface, TyAndLayout};
 use crate::spec::{self, HasTargetSpec};
 use rustc_span::Symbol;
-use std::fmt;
 use std::str::FromStr;
 
 mod aarch64;
@@ -633,16 +632,6 @@ pub enum AdjustForForeignAbiError {
     Unsupported { arch: Symbol, abi: spec::abi::Abi },
 }
 
-impl fmt::Display for AdjustForForeignAbiError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
-            Self::Unsupported { arch, abi } => {
-                write!(f, "target architecture {arch:?} does not support `extern {abi}` ABI")
-            }
-        }
-    }
-}
-
 impl<'a, Ty> FnAbi<'a, Ty> {
     pub fn adjust_for_foreign_abi<C>(
         &mut self,
diff --git a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs
index fc5dbd114e4..b9df0046b12 100644
--- a/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/mips64_unknown_linux_gnuabi64.rs
@@ -12,7 +12,7 @@ pub fn target() -> Target {
             endian: Endian::Big,
             // NOTE(mips64r2) matches C toolchain
             cpu: "mips64r2".into(),
-            features: "+mips64r2".into(),
+            features: "+mips64r2,+xgot".into(),
             max_atomic_width: Some(64),
             mcount: "_mcount".into(),
 
diff --git a/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs
index e0d5f6f57f1..57ad8c47399 100644
--- a/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/mips64el_unknown_linux_gnuabi64.rs
@@ -10,7 +10,7 @@ pub fn target() -> Target {
             abi: "abi64".into(),
             // NOTE(mips64r2) matches C toolchain
             cpu: "mips64r2".into(),
-            features: "+mips64r2".into(),
+            features: "+mips64r2,+xgot".into(),
             max_atomic_width: Some(64),
             mcount: "_mcount".into(),
 
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 9012bda4043..1470dc452a1 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1776,6 +1776,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     || !trait_pred
                         .skip_binder()
                         .is_constness_satisfied_by(self.tcx.constness(def_id))
+                    || !self.tcx.is_user_visible_dep(def_id.krate)
                 {
                     return None;
                 }
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 9582479941b..048302187cf 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -526,7 +526,7 @@ fn virtual_call_violation_for_method<'tcx>(
                         // #78372
                         tcx.sess.delay_span_bug(
                             tcx.def_span(method.def_id),
-                            format!("error: {}\n while computing layout for type {:?}", err, ty),
+                            format!("error: {err}\n while computing layout for type {ty:?}"),
                         );
                         None
                     }
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index 01d1fdc9b2a..8c4f6a73d7f 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -38,7 +38,6 @@ extern "Rust" {
     #[rustc_nounwind]
     fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8;
 
-    #[cfg(not(bootstrap))]
     static __rust_no_alloc_shim_is_unstable: u8;
 }
 
@@ -96,7 +95,6 @@ pub unsafe fn alloc(layout: Layout) -> *mut u8 {
     unsafe {
         // Make sure we don't accidentally allow omitting the allocator shim in
         // stable code until it is actually stabilized.
-        #[cfg(not(bootstrap))]
         core::ptr::read_volatile(&__rust_no_alloc_shim_is_unstable);
 
         __rust_alloc(layout.size(), layout.align())
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index c524d4c0367..59e3f887b52 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -2624,7 +2624,7 @@ impl ToString for String {
 }
 
 #[cfg(not(no_global_oom_handling))]
-#[stable(feature = "fmt_arguments_to_string_specialization", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "fmt_arguments_to_string_specialization", since = "1.71.0")]
 impl ToString for fmt::Arguments<'_> {
     #[inline]
     fn to_string(&self) -> String {
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index 38a6d1ccdb5..799085e9a83 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -495,8 +495,7 @@ pub trait Into<T>: Sized {
 /// By converting underlying error types to our own custom error type that encapsulates the
 /// underlying error type, we can return a single error type without losing information on the
 /// underlying cause. The '?' operator automatically converts the underlying error type to our
-/// custom error type by calling `Into<CliError>::into` which is automatically provided when
-/// implementing `From`. The compiler then infers which implementation of `Into` should be used.
+/// custom error type with `From::from`.
 ///
 /// ```
 /// use std::fs;
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 201bacb28c7..50c7516b7fe 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -81,7 +81,7 @@ use crate::str;
 #[derive(Hash)]
 #[stable(feature = "core_c_str", since = "1.64.0")]
 #[rustc_has_incoherent_inherent_impls]
-#[cfg_attr(not(bootstrap), lang = "CStr")]
+#[lang = "CStr"]
 // FIXME:
 // `fn from` in `impl From<&CStr> for Box<CStr>` current implementation relies
 // on `CStr` being layout-compatible with `[u8]`.
@@ -531,8 +531,8 @@ impl CStr {
     /// # }
     /// ```
     #[inline]
-    #[stable(feature = "cstr_is_empty", since = "CURRENT_RUSTC_VERSION")]
-    #[rustc_const_stable(feature = "cstr_is_empty", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "cstr_is_empty", since = "1.71.0")]
+    #[rustc_const_stable(feature = "cstr_is_empty", since = "1.71.0")]
     pub const fn is_empty(&self) -> bool {
         // SAFETY: We know there is at least one byte; for empty strings it
         // is the NUL terminator.
diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs
index b73abbbaca7..86ea154a886 100644
--- a/library/core/src/ffi/mod.rs
+++ b/library/core/src/ffi/mod.rs
@@ -202,7 +202,7 @@ mod c_long_definition {
 //     would be uninhabited and at least dereferencing such pointers would
 //     be UB.
 #[doc = include_str!("c_void.md")]
-#[cfg_attr(not(bootstrap), lang = "c_void")]
+#[lang = "c_void"]
 #[cfg_attr(not(doc), repr(u8))] // work around https://github.com/rust-lang/rust/issues/90435
 #[stable(feature = "core_c_void", since = "1.30.0")]
 pub enum c_void {
diff --git a/library/core/src/hash/mod.rs b/library/core/src/hash/mod.rs
index ca7c0772de8..794a57f0922 100644
--- a/library/core/src/hash/mod.rs
+++ b/library/core/src/hash/mod.rs
@@ -695,7 +695,7 @@ pub trait BuildHasher {
     ///     bh.hash_one(&OrderAmbivalentPair(2, 10))
     /// );
     /// ```
-    #[stable(feature = "build_hasher_simple_hash_one", since = "CURRENT_RUSTC_VERSION")]
+    #[stable(feature = "build_hasher_simple_hash_one", since = "1.71.0")]
     fn hash_one<T: Hash>(&self, x: T) -> u64
     where
         Self: Sized,
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 23ded42fa66..6dca1fe1e69 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1385,7 +1385,6 @@ extern "rust-intrinsic" {
     ///
     /// This is not expected to ever be exposed directly to users, rather it
     /// may eventually be exposed through some more-constrained API.
-    #[cfg(not(bootstrap))]
     #[rustc_const_stable(feature = "const_transmute", since = "1.56.0")]
     #[rustc_nounwind]
     pub fn transmute_unchecked<Src, Dst>(src: Src) -> Dst;
@@ -1425,19 +1424,11 @@ extern "rust-intrinsic" {
     /// returned value will result in undefined behavior.
     ///
     /// The stabilized version of this intrinsic is [`pointer::offset`].
-    #[cfg(not(bootstrap))]
     #[must_use = "returns a new pointer rather than modifying its argument"]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[rustc_nounwind]
     pub fn offset<Ptr, Delta>(dst: Ptr, offset: Delta) -> Ptr;
 
-    /// The bootstrap version of this is more restricted.
-    #[cfg(bootstrap)]
-    #[must_use = "returns a new pointer rather than modifying its argument"]
-    #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
-    #[rustc_nounwind]
-    pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
-
     /// Calculates the offset from a pointer, potentially wrapping.
     ///
     /// This is implemented as an intrinsic to avoid converting to and from an
@@ -2260,7 +2251,7 @@ extern "rust-intrinsic" {
     /// This intrinsic can *only* be called where the pointer is a local without
     /// projections (`read_via_copy(ptr)`, not `read_via_copy(*ptr)`) so that it
     /// trivially obeys runtime-MIR rules about derefs in operands.
-    #[rustc_const_stable(feature = "const_ptr_read", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")]
     #[rustc_nounwind]
     pub fn read_via_copy<T>(ptr: *const T) -> T;
 
@@ -2270,7 +2261,6 @@ extern "rust-intrinsic" {
     /// This intrinsic can *only* be called where the pointer is a local without
     /// projections (`write_via_move(ptr, x)`, not `write_via_move(*ptr, x)`) so
     /// that it trivially obeys runtime-MIR rules about derefs in operands.
-    #[cfg(not(bootstrap))]
     #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
     #[rustc_nounwind]
     pub fn write_via_move<T>(ptr: *mut T, value: T);
@@ -2832,24 +2822,3 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
         write_bytes(dst, val, count)
     }
 }
-
-/// Polyfill for bootstrap
-#[cfg(bootstrap)]
-pub const unsafe fn transmute_unchecked<Src, Dst>(src: Src) -> Dst {
-    use crate::mem::*;
-    // SAFETY: It's a transmute -- the caller promised it's fine.
-    unsafe { transmute_copy(&ManuallyDrop::new(src)) }
-}
-
-/// Polyfill for bootstrap
-#[cfg(bootstrap)]
-pub const unsafe fn write_via_move<T>(ptr: *mut T, value: T) {
-    use crate::mem::*;
-    // SAFETY: the caller must guarantee that `dst` is valid for writes.
-    // `dst` cannot overlap `src` because the caller has mutable access
-    // to `dst` while `src` is owned by this function.
-    unsafe {
-        copy_nonoverlapping::<T>(&value, ptr, 1);
-        forget(value);
-    }
-}
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 8dab8d1a692..2d2d5d49175 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -971,7 +971,7 @@ pub trait Tuple {}
 pub trait PointerLike {}
 
 /// A marker for types which can be used as types of `const` generic parameters.
-#[cfg_attr(not(bootstrap), lang = "const_param_ty")]
+#[lang = "const_param_ty"]
 #[unstable(feature = "adt_const_params", issue = "95174")]
 #[rustc_on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
 pub trait ConstParamTy: StructuralEq {}
@@ -979,7 +979,6 @@ pub trait ConstParamTy: StructuralEq {}
 /// Derive macro generating an impl of the trait `ConstParamTy`.
 #[rustc_builtin_macro]
 #[unstable(feature = "adt_const_params", issue = "95174")]
-#[cfg(not(bootstrap))]
 pub macro ConstParamTy($item:item) {
     /* compiler built-in */
 }
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index afbfd6d362d..39c9a04eea9 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -968,7 +968,7 @@ pub const fn replace<T>(dest: &mut T, src: T) -> T {
 /// Integers and other types implementing [`Copy`] are unaffected by `drop`.
 ///
 /// ```
-/// # #![cfg_attr(not(bootstrap), allow(dropping_copy_types))]
+/// # #![allow(dropping_copy_types)]
 /// #[derive(Copy, Clone)]
 /// struct Foo(u8);
 ///
@@ -1316,7 +1316,6 @@ impl<T> SizedTypeProperties for T {}
 ///
 /// assert_eq!(mem::offset_of!(NestedA, b.0), 0);
 /// ```
-#[cfg(not(bootstrap))]
 #[unstable(feature = "offset_of", issue = "106655")]
 #[allow_internal_unstable(builtin_syntax)]
 pub macro offset_of($Container:ty, $($fields:tt).+ $(,)?) {
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 38a1c42d9e8..7f06e170ad0 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -769,8 +769,8 @@ macro_rules! nonzero_signed_operations {
                 /// ```
                 #[must_use]
                 #[inline]
-                #[stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
-                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
+                #[stable(feature = "nonzero_negation_ops", since = "1.71.0")]
+                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")]
                 pub const fn is_positive(self) -> bool {
                     self.get().is_positive()
                 }
@@ -794,8 +794,8 @@ macro_rules! nonzero_signed_operations {
                 /// ```
                 #[must_use]
                 #[inline]
-                #[stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
-                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
+                #[stable(feature = "nonzero_negation_ops", since = "1.71.0")]
+                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")]
                 pub const fn is_negative(self) -> bool {
                     self.get().is_negative()
                 }
@@ -819,8 +819,8 @@ macro_rules! nonzero_signed_operations {
                 /// # }
                 /// ```
                 #[inline]
-                #[stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
-                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
+                #[stable(feature = "nonzero_negation_ops", since = "1.71.0")]
+                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")]
                 pub const fn checked_neg(self) -> Option<$Ty> {
                     if let Some(result) = self.get().checked_neg() {
                         // SAFETY: negation of nonzero cannot yield zero values.
@@ -851,8 +851,8 @@ macro_rules! nonzero_signed_operations {
                 /// # }
                 /// ```
                 #[inline]
-                #[stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
-                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
+                #[stable(feature = "nonzero_negation_ops", since = "1.71.0")]
+                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")]
                 pub const fn overflowing_neg(self) -> ($Ty, bool) {
                     let (result, overflow) = self.get().overflowing_neg();
                     // SAFETY: negation of nonzero cannot yield zero values.
@@ -884,8 +884,8 @@ macro_rules! nonzero_signed_operations {
                 /// # }
                 /// ```
                 #[inline]
-                #[stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
-                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
+                #[stable(feature = "nonzero_negation_ops", since = "1.71.0")]
+                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")]
                 pub const fn saturating_neg(self) -> $Ty {
                     if let Some(result) = self.checked_neg() {
                         return result;
@@ -916,8 +916,8 @@ macro_rules! nonzero_signed_operations {
                 /// # }
                 /// ```
                 #[inline]
-                #[stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
-                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "CURRENT_RUSTC_VERSION")]
+                #[stable(feature = "nonzero_negation_ops", since = "1.71.0")]
+                #[rustc_const_stable(feature = "nonzero_negation_ops", since = "1.71.0")]
                 pub const fn wrapping_neg(self) -> $Ty {
                     let result = self.get().wrapping_neg();
                     // SAFETY: negation of nonzero cannot yield zero values.
@@ -925,7 +925,7 @@ macro_rules! nonzero_signed_operations {
                 }
             }
 
-            #[stable(feature = "signed_nonzero_neg", since = "CURRENT_RUSTC_VERSION")]
+            #[stable(feature = "signed_nonzero_neg", since = "1.71.0")]
             impl Neg for $Ty {
                 type Output = $Ty;
 
@@ -937,7 +937,7 @@ macro_rules! nonzero_signed_operations {
             }
 
             forward_ref_unop! { impl Neg, neg for $Ty,
-                #[stable(feature = "signed_nonzero_neg", since = "CURRENT_RUSTC_VERSION")] }
+                #[stable(feature = "signed_nonzero_neg", since = "1.71.0")] }
         )+
     }
 }
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 5ee1b5e4afc..926189a17b2 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -104,6 +104,7 @@ impl<T: ?Sized> *const T {
     /// refactored.
     #[stable(feature = "ptr_const_cast", since = "1.65.0")]
     #[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")]
+    #[rustc_diagnostic_item = "ptr_cast_mut"]
     #[inline(always)]
     pub const fn cast_mut(self) -> *mut T {
         self as _
@@ -916,16 +917,8 @@ impl<T: ?Sized> *const T {
     where
         T: Sized,
     {
-        #[cfg(bootstrap)]
         // SAFETY: the caller must uphold the safety contract for `offset`.
-        unsafe {
-            self.offset(count as isize)
-        }
-        #[cfg(not(bootstrap))]
-        // SAFETY: the caller must uphold the safety contract for `offset`.
-        unsafe {
-            intrinsics::offset(self, count)
-        }
+        unsafe { intrinsics::offset(self, count) }
     }
 
     /// Calculates the offset from a pointer in bytes (convenience for `.byte_offset(count as isize)`).
@@ -1195,7 +1188,7 @@ impl<T: ?Sized> *const T {
     ///
     /// [`ptr::read`]: crate::ptr::read()
     #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[rustc_const_stable(feature = "const_ptr_read", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")]
     #[inline]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn read(self) -> T
@@ -1236,7 +1229,7 @@ impl<T: ?Sized> *const T {
     ///
     /// [`ptr::read_unaligned`]: crate::ptr::read_unaligned()
     #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[rustc_const_stable(feature = "const_ptr_read", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")]
     #[inline]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn read_unaligned(self) -> T
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index ff9fa48f311..acc9ca29d41 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -698,6 +698,7 @@ where
 #[inline(always)]
 #[must_use]
 #[unstable(feature = "ptr_from_ref", issue = "106116")]
+#[rustc_diagnostic_item = "ptr_from_ref"]
 pub const fn from_ref<T: ?Sized>(r: &T) -> *const T {
     r
 }
@@ -1139,7 +1140,7 @@ pub const unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
 /// [valid]: self#safety
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_stable(feature = "const_ptr_read", since = "CURRENT_RUSTC_VERSION")]
+#[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")]
 #[rustc_allow_const_fn_unstable(const_mut_refs, const_maybe_uninit_as_mut_ptr)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 pub const unsafe fn read<T>(src: *const T) -> T {
@@ -1256,7 +1257,7 @@ pub const unsafe fn read<T>(src: *const T) -> T {
 /// ```
 #[inline]
 #[stable(feature = "ptr_unaligned", since = "1.17.0")]
-#[rustc_const_stable(feature = "const_ptr_read", since = "CURRENT_RUSTC_VERSION")]
+#[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")]
 #[rustc_allow_const_fn_unstable(const_mut_refs, const_maybe_uninit_as_mut_ptr)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 pub const unsafe fn read_unaligned<T>(src: *const T) -> T {
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 5edd291fb76..c6f43857887 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -473,20 +473,10 @@ impl<T: ?Sized> *mut T {
     where
         T: Sized,
     {
-        #[cfg(bootstrap)]
         // SAFETY: the caller must uphold the safety contract for `offset`.
         // The obtained pointer is valid for writes since the caller must
         // guarantee that it points to the same allocated object as `self`.
-        unsafe {
-            intrinsics::offset(self, count) as *mut T
-        }
-        #[cfg(not(bootstrap))]
-        // SAFETY: the caller must uphold the safety contract for `offset`.
-        // The obtained pointer is valid for writes since the caller must
-        // guarantee that it points to the same allocated object as `self`.
-        unsafe {
-            intrinsics::offset(self, count)
-        }
+        unsafe { intrinsics::offset(self, count) }
     }
 
     /// Calculates the offset from a pointer in bytes.
@@ -1026,16 +1016,8 @@ impl<T: ?Sized> *mut T {
     where
         T: Sized,
     {
-        #[cfg(bootstrap)]
-        // SAFETY: the caller must uphold the safety contract for `offset`.
-        unsafe {
-            self.offset(count as isize)
-        }
-        #[cfg(not(bootstrap))]
         // SAFETY: the caller must uphold the safety contract for `offset`.
-        unsafe {
-            intrinsics::offset(self, count)
-        }
+        unsafe { intrinsics::offset(self, count) }
     }
 
     /// Calculates the offset from a pointer in bytes (convenience for `.byte_offset(count as isize)`).
@@ -1305,7 +1287,7 @@ impl<T: ?Sized> *mut T {
     ///
     /// [`ptr::read`]: crate::ptr::read()
     #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[rustc_const_stable(feature = "const_ptr_read", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")]
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn read(self) -> T
@@ -1346,7 +1328,7 @@ impl<T: ?Sized> *mut T {
     ///
     /// [`ptr::read_unaligned`]: crate::ptr::read_unaligned()
     #[stable(feature = "pointer_methods", since = "1.26.0")]
-    #[rustc_const_stable(feature = "const_ptr_read", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")]
     #[inline(always)]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub const unsafe fn read_unaligned(self) -> T
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 62003ddf515..c87af35fbc4 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -1854,7 +1854,7 @@ impl<T> [T] {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_stable(feature = "const_slice_split_at_not_mut", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "const_slice_split_at_not_mut", since = "1.71.0")]
     #[rustc_allow_const_fn_unstable(slice_split_at_unchecked)]
     #[inline]
     #[track_caller]
diff --git a/library/core/src/tuple.rs b/library/core/src/tuple.rs
index 172e5fccb61..a1388dfeee6 100644
--- a/library/core/src/tuple.rs
+++ b/library/core/src/tuple.rs
@@ -100,7 +100,7 @@ macro_rules! tuple_impls {
             }
         }
 
-        #[stable(feature = "array_tuple_conv", since = "CURRENT_RUSTC_VERSION")]
+        #[stable(feature = "array_tuple_conv", since = "1.71.0")]
         impl<T> From<[T; ${count(T)}]> for ($(${ignore(T)} T,)+) {
             #[inline]
             #[allow(non_snake_case)]
@@ -110,7 +110,7 @@ macro_rules! tuple_impls {
             }
         }
 
-        #[stable(feature = "array_tuple_conv", since = "CURRENT_RUSTC_VERSION")]
+        #[stable(feature = "array_tuple_conv", since = "1.71.0")]
         impl<T> From<($(${ignore(T)} T,)+)> for [T; ${count(T)}] {
             #[inline]
             #[allow(non_snake_case)]
diff --git a/library/core/tests/clone.rs b/library/core/tests/clone.rs
index aafe5ced2e9..64193e11558 100644
--- a/library/core/tests/clone.rs
+++ b/library/core/tests/clone.rs
@@ -1,5 +1,5 @@
 #[test]
-#[cfg_attr(not(bootstrap), allow(suspicious_double_ref_op))]
+#[allow(suspicious_double_ref_op)]
 fn test_borrowed_clone() {
     let x = 5;
     let y: &i32 = &x;
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 3933e328951..3e6d31fcd2f 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -109,7 +109,7 @@
 #![feature(utf8_chunks)]
 #![feature(is_ascii_octdigit)]
 #![feature(get_many_mut)]
-#![cfg_attr(not(bootstrap), feature(offset_of))]
+#![feature(offset_of)]
 #![deny(unsafe_op_in_unsafe_fn)]
 #![deny(fuzzy_provenance_casts)]
 
diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs
index aee9c89b595..5c2e18745ea 100644
--- a/library/core/tests/mem.rs
+++ b/library/core/tests/mem.rs
@@ -366,7 +366,6 @@ fn const_maybe_uninit() {
 }
 
 #[test]
-#[cfg(not(bootstrap))]
 fn offset_of() {
     #[repr(C)]
     struct Foo {
@@ -391,7 +390,7 @@ fn offset_of() {
     struct Generic<T> {
         x: u8,
         y: u32,
-        z: T
+        z: T,
     }
 
     trait Trait {}
@@ -409,7 +408,6 @@ fn offset_of() {
 }
 
 #[test]
-#[cfg(not(bootstrap))]
 fn offset_of_union() {
     #[repr(C)]
     union Foo {
@@ -429,7 +427,6 @@ fn offset_of_union() {
 }
 
 #[test]
-#[cfg(not(bootstrap))]
 fn offset_of_dst() {
     #[repr(C)]
     struct Alpha {
@@ -469,7 +466,6 @@ fn offset_of_dst() {
 }
 
 #[test]
-#[cfg(not(bootstrap))]
 fn offset_of_packed() {
     #[repr(C, packed)]
     struct Foo {
@@ -482,7 +478,6 @@ fn offset_of_packed() {
 }
 
 #[test]
-#[cfg(not(bootstrap))]
 fn offset_of_projection() {
     #[repr(C)]
     struct Foo {
@@ -503,7 +498,6 @@ fn offset_of_projection() {
 }
 
 #[test]
-#[cfg(not(bootstrap))]
 fn offset_of_alias() {
     #[repr(C)]
     struct Foo {
@@ -518,7 +512,6 @@ fn offset_of_alias() {
 }
 
 #[test]
-#[cfg(not(bootstrap))]
 fn const_offset_of() {
     #[repr(C)]
     struct Foo {
@@ -534,7 +527,6 @@ fn const_offset_of() {
 }
 
 #[test]
-#[cfg(not(bootstrap))]
 fn offset_of_without_const_promotion() {
     #[repr(C)]
     struct Foo<SuppressConstPromotion> {
@@ -555,7 +547,6 @@ fn offset_of_without_const_promotion() {
 }
 
 #[test]
-#[cfg(not(bootstrap))]
 fn offset_of_addr() {
     #[repr(C)]
     struct Foo {
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 824abc72a22..72d910bf957 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -1,3 +1,5 @@
+cargo-features = ["public-dependency"]
+
 [package]
 name = "std"
 version = "0.0.0"
@@ -10,12 +12,12 @@ edition = "2021"
 crate-type = ["dylib", "rlib"]
 
 [dependencies]
-alloc = { path = "../alloc" }
+alloc = { path = "../alloc", public = true }
 cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
 panic_unwind = { path = "../panic_unwind", optional = true }
 panic_abort = { path = "../panic_abort" }
-core = { path = "../core" }
-libc = { version = "0.2.143", default-features = false, features = ['rustc-dep-of-std'] }
+core = { path = "../core", public = true }
+libc = { version = "0.2.143", default-features = false, features = ['rustc-dep-of-std'], public = true }
 compiler_builtins = { version = "0.1.92" }
 profiler_builtins = { path = "../profiler_builtins", optional = true }
 unwind = { path = "../unwind" }
@@ -25,7 +27,7 @@ std_detect = { path = "../stdarch/crates/std_detect", default-features = false,
 # Dependencies of the `backtrace` crate
 addr2line = { version = "0.19.0", optional = true, default-features = false }
 rustc-demangle = { version = "0.1.21", features = ['rustc-dep-of-std'] }
-miniz_oxide = { version = "0.6.0", optional = true, default-features = false }
+miniz_oxide = { version = "0.6.0", optional = true, default-features = false, public = false }
 [dependencies.object]
 version = "0.30.0"
 optional = true
@@ -40,7 +42,7 @@ rand_xorshift = "0.3.0"
 dlmalloc = { version = "0.2.3", features = ['rustc-dep-of-std'] }
 
 [target.x86_64-fortanix-unknown-sgx.dependencies]
-fortanix-sgx-abi = { version = "0.5.0", features = ['rustc-dep-of-std'] }
+fortanix-sgx-abi = { version = "0.5.0", features = ['rustc-dep-of-std'], public = true }
 
 [target.'cfg(target_os = "hermit")'.dependencies]
 hermit-abi = { version = "0.3.0", features = ['rustc-dep-of-std'] }
diff --git a/library/std/src/os/windows/io/handle.rs b/library/std/src/os/windows/io/handle.rs
index cbf8209a5ad..274af08a388 100644
--- a/library/std/src/os/windows/io/handle.rs
+++ b/library/std/src/os/windows/io/handle.rs
@@ -437,7 +437,7 @@ impl<T: AsHandle> AsHandle for &mut T {
     }
 }
 
-#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "as_windows_ptrs", since = "1.71.0")]
 /// This impl allows implementing traits that require `AsHandle` on Arc.
 /// ```
 /// # #[cfg(windows)] mod group_cfg {
@@ -457,7 +457,7 @@ impl<T: AsHandle> AsHandle for crate::sync::Arc<T> {
     }
 }
 
-#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "as_windows_ptrs", since = "1.71.0")]
 impl<T: AsHandle> AsHandle for crate::rc::Rc<T> {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
@@ -465,7 +465,7 @@ impl<T: AsHandle> AsHandle for crate::rc::Rc<T> {
     }
 }
 
-#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "as_windows_ptrs", since = "1.71.0")]
 impl<T: AsHandle> AsHandle for Box<T> {
     #[inline]
     fn as_handle(&self) -> BorrowedHandle<'_> {
diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs
index 0c90d55c024..6359835cad5 100644
--- a/library/std/src/os/windows/io/socket.rs
+++ b/library/std/src/os/windows/io/socket.rs
@@ -254,7 +254,7 @@ impl<T: AsSocket> AsSocket for &mut T {
     }
 }
 
-#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "as_windows_ptrs", since = "1.71.0")]
 /// This impl allows implementing traits that require `AsSocket` on Arc.
 /// ```
 /// # #[cfg(windows)] mod group_cfg {
@@ -274,7 +274,7 @@ impl<T: AsSocket> AsSocket for crate::sync::Arc<T> {
     }
 }
 
-#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "as_windows_ptrs", since = "1.71.0")]
 impl<T: AsSocket> AsSocket for crate::rc::Rc<T> {
     #[inline]
     fn as_socket(&self) -> BorrowedSocket<'_> {
@@ -282,7 +282,7 @@ impl<T: AsSocket> AsSocket for crate::rc::Rc<T> {
     }
 }
 
-#[stable(feature = "as_windows_ptrs", since = "CURRENT_RUSTC_VERSION")]
+#[stable(feature = "as_windows_ptrs", since = "1.71.0")]
 impl<T: AsSocket> AsSocket for Box<T> {
     #[inline]
     fn as_socket(&self) -> BorrowedSocket<'_> {
diff --git a/library/std/src/sys/wasi/fd.rs b/library/std/src/sys/wasi/fd.rs
index 9a8b2a0be5b..1b50c2ea6dd 100644
--- a/library/std/src/sys/wasi/fd.rs
+++ b/library/std/src/sys/wasi/fd.rs
@@ -96,7 +96,7 @@ impl WasiFd {
         unsafe { wasi::fd_sync(self.as_raw_fd() as wasi::Fd).map_err(err2io) }
     }
 
-    pub fn advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()> {
+    pub(crate) fn advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()> {
         unsafe {
             wasi::fd_advise(self.as_raw_fd() as wasi::Fd, offset, len, advice).map_err(err2io)
         }
@@ -179,7 +179,7 @@ impl WasiFd {
         }
     }
 
-    pub fn filestat_get(&self) -> io::Result<wasi::Filestat> {
+    pub(crate) fn filestat_get(&self) -> io::Result<wasi::Filestat> {
         unsafe { wasi::fd_filestat_get(self.as_raw_fd() as wasi::Fd).map_err(err2io) }
     }
 
@@ -199,7 +199,7 @@ impl WasiFd {
         unsafe { wasi::fd_filestat_set_size(self.as_raw_fd() as wasi::Fd, size).map_err(err2io) }
     }
 
-    pub fn path_filestat_get(
+    pub(crate) fn path_filestat_get(
         &self,
         flags: wasi::Lookupflags,
         path: &str,
diff --git a/library/std/src/sys/wasi/fs.rs b/library/std/src/sys/wasi/fs.rs
index 8d1dbf59155..437aae3ae7f 100644
--- a/library/std/src/sys/wasi/fs.rs
+++ b/library/std/src/sys/wasi/fs.rs
@@ -104,7 +104,7 @@ impl FileAttr {
         Ok(SystemTime::from_wasi_timestamp(self.meta.ctim))
     }
 
-    pub fn as_wasi(&self) -> &wasi::Filestat {
+    pub(crate) fn as_wasi(&self) -> &wasi::Filestat {
         &self.meta
     }
 }
@@ -142,7 +142,7 @@ impl FileType {
         self.bits == wasi::FILETYPE_SYMBOLIC_LINK
     }
 
-    pub fn bits(&self) -> wasi::Filetype {
+    pub(crate) fn bits(&self) -> wasi::Filetype {
         self.bits
     }
 }
diff --git a/library/std/src/sys/windows/stdio.rs b/library/std/src/sys/windows/stdio.rs
index 2e3e0859dc1..3fcaaa508e3 100644
--- a/library/std/src/sys/windows/stdio.rs
+++ b/library/std/src/sys/windows/stdio.rs
@@ -11,6 +11,9 @@ use crate::sys::cvt;
 use crate::sys::handle::Handle;
 use core::str::utf8_char_width;
 
+#[cfg(test)]
+mod tests;
+
 // Don't cache handles but get them fresh for every read/write. This allows us to track changes to
 // the value over time (such as if a process calls `SetStdHandle` while it's running). See #40490.
 pub struct Stdin {
@@ -383,6 +386,10 @@ fn utf16_to_utf8(utf16: &[u16], utf8: &mut [u8]) -> io::Result<usize> {
     debug_assert!(utf16.len() <= c::c_int::MAX as usize);
     debug_assert!(utf8.len() <= c::c_int::MAX as usize);
 
+    if utf16.is_empty() {
+        return Ok(0);
+    }
+
     let result = unsafe {
         c::WideCharToMultiByte(
             c::CP_UTF8,              // CodePage
diff --git a/library/std/src/sys/windows/stdio/tests.rs b/library/std/src/sys/windows/stdio/tests.rs
new file mode 100644
index 00000000000..1e53e0bee63
--- /dev/null
+++ b/library/std/src/sys/windows/stdio/tests.rs
@@ -0,0 +1,6 @@
+use super::utf16_to_utf8;
+
+#[test]
+fn zero_size_read() {
+    assert_eq!(utf16_to_utf8(&[], &mut []).unwrap(), 0);
+}
diff --git a/library/std/tests/common/mod.rs b/library/std/tests/common/mod.rs
index fce220223a0..358c2c3f9b2 100644
--- a/library/std/tests/common/mod.rs
+++ b/library/std/tests/common/mod.rs
@@ -20,15 +20,15 @@ pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng {
 }
 
 // Copied from std::sys_common::io
-pub struct TempDir(PathBuf);
+pub(crate) struct TempDir(PathBuf);
 
 impl TempDir {
-    pub fn join(&self, path: &str) -> PathBuf {
+    pub(crate) fn join(&self, path: &str) -> PathBuf {
         let TempDir(ref p) = *self;
         p.join(path)
     }
 
-    pub fn path(&self) -> &Path {
+    pub(crate) fn path(&self) -> &Path {
         let TempDir(ref p) = *self;
         p
     }
@@ -49,7 +49,7 @@ impl Drop for TempDir {
 }
 
 #[track_caller] // for `test_rng`
-pub fn tmpdir() -> TempDir {
+pub(crate) fn tmpdir() -> TempDir {
     let p = env::temp_dir();
     let mut r = test_rng();
     let ret = p.join(&format!("rust-{}", r.next_u32()));
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 58d1926ad96..473fdbe1edc 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -835,7 +835,7 @@ class RustBuild(object):
         """
         return os.path.join(self.build_dir, "bootstrap", "debug", "bootstrap")
 
-    def build_bootstrap(self, color, verbose_count):
+    def build_bootstrap(self, color, warnings, verbose_count):
         """Build bootstrap"""
         env = os.environ.copy()
         if "GITHUB_ACTIONS" in env:
@@ -877,6 +877,12 @@ class RustBuild(object):
 
         # preserve existing RUSTFLAGS
         env.setdefault("RUSTFLAGS", "")
+        # we need to explicitly add +xgot here so that we can successfully bootstrap
+        # a usable stage1 compiler
+        # FIXME: remove this if condition on the next bootstrap bump
+        # cfg(bootstrap)
+        if self.build_triple().startswith('mips'):
+            env["RUSTFLAGS"] += " -Ctarget-feature=+xgot"
         target_features = []
         if self.get_toml("crt-static", build_section) == "true":
             target_features += ["+crt-static"]
@@ -888,7 +894,11 @@ class RustBuild(object):
         if target_linker is not None:
             env["RUSTFLAGS"] += " -C linker=" + target_linker
         env["RUSTFLAGS"] += " -Wrust_2018_idioms -Wunused_lifetimes"
-        if self.get_toml("deny-warnings", "rust") != "false":
+        if warnings == "default":
+            deny_warnings = self.get_toml("deny-warnings", "rust") != "false"
+        else:
+            deny_warnings = warnings == "deny"
+        if deny_warnings:
             env["RUSTFLAGS"] += " -Dwarnings"
 
         env["PATH"] = os.path.join(self.bin_root(), "bin") + \
@@ -912,6 +922,10 @@ class RustBuild(object):
             args.append("--color=always")
         elif color == "never":
             args.append("--color=never")
+        try:
+            args += env["CARGOFLAGS"].split()
+        except KeyError:
+            pass
 
         # Run this from the source directory so cargo finds .cargo/config
         run(args, env=env, verbose=self.verbose, cwd=self.rust_root)
@@ -977,6 +991,7 @@ def parse_args():
     parser.add_argument('--color', choices=['always', 'never', 'auto'])
     parser.add_argument('--clean', action='store_true')
     parser.add_argument('--json-output', action='store_true')
+    parser.add_argument('--warnings', choices=['deny', 'warn', 'default'], default='default')
     parser.add_argument('-v', '--verbose', action='count', default=0)
 
     return parser.parse_known_args(sys.argv)[0]
@@ -1042,7 +1057,7 @@ def bootstrap(args):
     # Fetch/build the bootstrap
     build.download_toolchain()
     sys.stdout.flush()
-    build.build_bootstrap(args.color, verbose_count)
+    build.build_bootstrap(args.color, args.warnings, verbose_count)
     sys.stdout.flush()
 
     # Run the bootstrap
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 46fc5b80e99..6a2409a0fbf 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -1009,6 +1009,9 @@ impl Step for PlainSourceTarball {
                 .arg(builder.src.join("./compiler/rustc_codegen_cranelift/Cargo.toml"))
                 .arg("--sync")
                 .arg(builder.src.join("./src/bootstrap/Cargo.toml"))
+                // Will read the libstd Cargo.toml
+                // which uses the unstable `public-dependency` feature.
+                .env("RUSTC_BOOTSTRAP", "1")
                 .current_dir(&plain_dst_src);
 
             let config = if !builder.config.dry_run() {
diff --git a/src/bootstrap/metadata.rs b/src/bootstrap/metadata.rs
index 8f2c3faca3a..3b20ceac875 100644
--- a/src/bootstrap/metadata.rs
+++ b/src/bootstrap/metadata.rs
@@ -74,6 +74,9 @@ fn workspace_members(build: &Build) -> impl Iterator<Item = Package> {
     let collect_metadata = |manifest_path| {
         let mut cargo = Command::new(&build.initial_cargo);
         cargo
+            // Will read the libstd Cargo.toml
+            // which uses the unstable `public-dependency` feature.
+            .env("RUSTC_BOOTSTRAP", "1")
             .arg("metadata")
             .arg("--format-version")
             .arg("1")
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 2924ba0bdf1..eec8c4ad69f 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1704,10 +1704,6 @@ note: if you're sure you want to do this, please open an issue as to why. In the
             cmd.arg("--git-hash");
         }
 
-        if let Some(commit) = builder.config.download_rustc_commit() {
-            cmd.env("FAKE_DOWNLOAD_RUSTC_PREFIX", format!("/rustc/{commit}"));
-        }
-
         builder.ci_env.force_coloring_in_ci(&mut cmd);
 
         #[cfg(feature = "build-metrics")]
@@ -1776,6 +1772,14 @@ impl Step for BookTest {
     ///
     /// This uses the `rustdoc` that sits next to `compiler`.
     fn run(self, builder: &Builder<'_>) {
+        let host = self.compiler.host;
+        let _guard = builder.msg(
+            Kind::Test,
+            self.compiler.stage,
+            &format!("book {}", self.name),
+            host,
+            host,
+        );
         // External docs are different from local because:
         // - Some books need pre-processing by mdbook before being tested.
         // - They need to save their state to toolstate.
@@ -1967,7 +1971,7 @@ fn markdown_test(builder: &Builder<'_>, compiler: Compiler, markdown: &Path) ->
         }
     }
 
-    builder.info(&format!("doc tests for: {}", markdown.display()));
+    builder.verbose(&format!("doc tests for: {}", markdown.display()));
     let mut cmd = builder.rustdoc_cmd(compiler);
     builder.add_rust_test_threads(&mut cmd);
     // allow for unstable options such as new editions
@@ -2503,6 +2507,9 @@ impl Step for Distcheck {
         let toml = dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
         builder.run(
             Command::new(&builder.initial_cargo)
+                // Will read the libstd Cargo.toml
+                // which uses the unstable `public-dependency` feature.
+                .env("RUSTC_BOOTSTRAP", "1")
                 .arg("generate-lockfile")
                 .arg("--manifest-path")
                 .arg(&toml)
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
index 04fdb15f5ac..c2fd2e3a91a 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile
@@ -55,7 +55,7 @@ RUN ./build-clang.sh
 ENV CC=clang CXX=clang++
 
 # rustc-perf version from 2023-03-15
-ENV PERF_COMMIT 9dfaa35193154b690922347ee1141a06ec87a199
+ENV PERF_COMMIT 8b2ac3042e1ff2c0074455a0a3618adef97156b1
 RUN curl -LS -o perf.zip https://github.com/rust-lang/rustc-perf/archive/$PERF_COMMIT.zip && \
     unzip perf.zip && \
     mv rustc-perf-$PERF_COMMIT rustc-perf && \
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh
index 8bea8cd4c87..2fe3438e0fe 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -264,6 +264,7 @@ docker \
   --env RUST_CI_OVERRIDE_RELEASE_CHANNEL \
   --env CI_JOB_NAME="${CI_JOB_NAME-$IMAGE}" \
   --env BASE_COMMIT="$BASE_COMMIT" \
+  --env DIST_TRY_BUILD \
   --init \
   --rm \
   rust-ci \
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index fd619467fc1..d3cb6b6ed52 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -757,6 +757,7 @@ jobs:
     <<: *base-ci-job
     name: try - ${{ matrix.name }}
     env:
+      DIST_TRY_BUILD: 1
       <<: [*shared-ci-variables, *prod-variables]
     if: github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'
     strategy:
diff --git a/src/ci/stage-build.py b/src/ci/stage-build.py
index 8d03d3759bf..4141296bd42 100644
--- a/src/ci/stage-build.py
+++ b/src/ci/stage-build.py
@@ -48,6 +48,11 @@ RUSTC_PGO_CRATES = [
 
 LLVM_BOLT_CRATES = LLVM_PGO_CRATES
 
+
+def is_try_build() -> bool:
+    return os.environ.get("DIST_TRY_BUILD", "0") != "0"
+
+
 class Pipeline:
     # Paths
     def checkout_path(self) -> Path:
@@ -175,7 +180,7 @@ class WindowsPipeline(Pipeline):
 
     def build_rustc_perf(self):
         # rustc-perf version from 2023-03-15
-        perf_commit = "9dfaa35193154b690922347ee1141a06ec87a199"
+        perf_commit = "8b2ac3042e1ff2c0074455a0a3618adef97156b1"
         rustc_perf_zip_path = self.opt_artifacts() / "perf.zip"
 
         def download_rustc_perf():
@@ -851,6 +856,13 @@ def run(runner: BenchmarkRunner):
 
     build_args = sys.argv[1:]
 
+    # Skip components that are not needed for try builds to speed them up
+    if is_try_build():
+        LOGGER.info("Skipping building of unimportant components for a try build")
+        for target in ("rust-docs", "rustc-docs", "rust-docs-json", "rust-analyzer",
+                       "rustc-src", "clippy", "miri", "rustfmt"):
+            build_args.extend(["--exclude", target])
+
     timer = Timer()
     pipeline = create_pipeline()
 
@@ -865,6 +877,7 @@ def run(runner: BenchmarkRunner):
 
     print_binary_sizes(pipeline)
 
+
 if __name__ == "__main__":
     runner = DefaultBenchmarkRunner()
     run(runner)
diff --git a/src/doc/unstable-book/src/language-features/const-eval-limit.md b/src/doc/unstable-book/src/language-features/const-eval-limit.md
deleted file mode 100644
index df68e83bcac..00000000000
--- a/src/doc/unstable-book/src/language-features/const-eval-limit.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# `const_eval_limit`
-
-The tracking issue for this feature is: [#67217]
-
-[#67217]: https://github.com/rust-lang/rust/issues/67217
-
-The `const_eval_limit` allows someone to limit the evaluation steps the CTFE undertakes to evaluate a `const fn`.
diff --git a/src/etc/pre-push.sh b/src/etc/pre-push.sh
index ff17931115c..0807e0492c1 100755
--- a/src/etc/pre-push.sh
+++ b/src/etc/pre-push.sh
@@ -14,4 +14,4 @@ ROOT_DIR="$(git rev-parse --show-toplevel)"
 echo "Running pre-push script $ROOT_DIR/x test tidy"
 
 cd "$ROOT_DIR"
-CARGOFLAGS="--locked" ./x test tidy
+./x test tidy --set build.locked-deps=true
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index b26a5c32ec6..1c27320024a 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -381,7 +381,6 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
             Some(Event::Code(text)) => {
                 trace!("saw code {}", text);
                 if let Some(link) = self.shortcut_link {
-                    trace!("original text was {}", link.original_text);
                     // NOTE: this only replaces if the code block is the *entire* text.
                     // If only part of the link has code highlighting, the disambiguator will not be removed.
                     // e.g. [fn@`f`]
@@ -390,8 +389,11 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
                     // So we could never be sure we weren't replacing too much:
                     // [fn@my_`f`unc] is treated the same as [my_func()] in that pass.
                     //
-                    // NOTE: &[1..len() - 1] is to strip the backticks
-                    if **text == link.original_text[1..link.original_text.len() - 1] {
+                    // NOTE: .get(1..len() - 1) is to strip the backticks
+                    if let Some(link) = self.links.iter().find(|l| {
+                        l.href == link.href
+                            && Some(&**text) == l.original_text.get(1..l.original_text.len() - 1)
+                    }) {
                         debug!("replacing {} with {}", text, link.new_text);
                         *text = CowStr::Borrowed(&link.new_text);
                     }
@@ -402,9 +404,12 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
             Some(Event::Text(text)) => {
                 trace!("saw text {}", text);
                 if let Some(link) = self.shortcut_link {
-                    trace!("original text was {}", link.original_text);
                     // NOTE: same limitations as `Event::Code`
-                    if **text == *link.original_text {
+                    if let Some(link) = self
+                        .links
+                        .iter()
+                        .find(|l| l.href == link.href && **text == *l.original_text)
+                    {
                         debug!("replacing {} with {}", text, link.new_text);
                         *text = CowStr::Borrowed(&link.new_text);
                     }
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index a7d5f497756..054cfe7597e 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -1179,6 +1179,10 @@ a.test-arrow:hover {
 	position: relative;
 }
 
+.code-header a.tooltip:hover {
+	color: var(--link-color);
+}
+
 /* placeholder thunk so that the mouse can easily travel from "(i)" to popover
 	the resulting "hover tunnel" is a stepped triangle, approximating
 	https://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown */
@@ -1191,6 +1195,14 @@ a.tooltip:hover::after {
 	content: "\00a0";
 }
 
+/* This animation is layered onto the mistake-proofing delay for dismissing
+	a hovered tooltip, to ensure it feels responsive even with the delay.
+	*/
+.fade-out {
+	opacity: 0;
+	transition: opacity 0.45s cubic-bezier(0, 0, 0.1, 1.0);
+}
+
 .popover.tooltip .content {
 	margin: 0.25em 0.5em;
 }
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index bccf675c14b..6da51ea0a55 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -4,6 +4,13 @@
 
 "use strict";
 
+// The amount of time that the cursor must remain still over a hover target before
+// revealing a tooltip.
+//
+// https://www.nngroup.com/articles/timing-exposing-content/
+window.RUSTDOC_TOOLTIP_HOVER_MS = 300;
+window.RUSTDOC_TOOLTIP_HOVER_EXIT_MS = 450;
+
 // Given a basename (e.g. "storage") and an extension (e.g. ".js"), return a URL
 // for a resource under the root-path, with the resource-suffix.
 function resourcePath(basename, extension) {
@@ -772,6 +779,13 @@ function preLoadCss(cssUrl) {
         });
     });
 
+    /**
+     * Show a tooltip immediately.
+     *
+     * @param {DOMElement} e - The tooltip's anchor point. The DOM is consulted to figure
+     *                         out what the tooltip should contain, and where it should be
+     *                         positioned.
+     */
     function showTooltip(e) {
         const notable_ty = e.getAttribute("data-notable-ty");
         if (!window.NOTABLE_TRAITS && notable_ty) {
@@ -782,8 +796,10 @@ function preLoadCss(cssUrl) {
                 throw new Error("showTooltip() called with notable without any notable traits!");
             }
         }
+        // Make this function idempotent. If the tooltip is already shown, avoid doing extra work
+        // and leave it alone.
         if (window.CURRENT_TOOLTIP_ELEMENT && window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE === e) {
-            // Make this function idempotent.
+            clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT);
             return;
         }
         window.hideAllModals(false);
@@ -791,11 +807,18 @@ function preLoadCss(cssUrl) {
         if (notable_ty) {
             wrapper.innerHTML = "<div class=\"content\">" +
                 window.NOTABLE_TRAITS[notable_ty] + "</div>";
-        } else if (e.getAttribute("title") !== undefined) {
-            const titleContent = document.createElement("div");
-            titleContent.className = "content";
-            titleContent.appendChild(document.createTextNode(e.getAttribute("title")));
-            wrapper.appendChild(titleContent);
+        } else {
+            // Replace any `title` attribute with `data-title` to avoid double tooltips.
+            if (e.getAttribute("title") !== null) {
+                e.setAttribute("data-title", e.getAttribute("title"));
+                e.removeAttribute("title");
+            }
+            if (e.getAttribute("data-title") !== null) {
+                const titleContent = document.createElement("div");
+                titleContent.className = "content";
+                titleContent.appendChild(document.createTextNode(e.getAttribute("data-title")));
+                wrapper.appendChild(titleContent);
+            }
         }
         wrapper.className = "tooltip popover";
         const focusCatcher = document.createElement("div");
@@ -824,17 +847,77 @@ function preLoadCss(cssUrl) {
         wrapper.style.visibility = "";
         window.CURRENT_TOOLTIP_ELEMENT = wrapper;
         window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE = e;
+        clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT);
+        wrapper.onpointerenter = function(ev) {
+            // If this is a synthetic touch event, ignore it. A click event will be along shortly.
+            if (ev.pointerType !== "mouse") {
+                return;
+            }
+            clearTooltipHoverTimeout(e);
+        };
         wrapper.onpointerleave = function(ev) {
             // If this is a synthetic touch event, ignore it. A click event will be along shortly.
             if (ev.pointerType !== "mouse") {
                 return;
             }
-            if (!e.TOOLTIP_FORCE_VISIBLE && !elemIsInParent(event.relatedTarget, e)) {
-                hideTooltip(true);
+            if (!e.TOOLTIP_FORCE_VISIBLE && !elemIsInParent(ev.relatedTarget, e)) {
+                // See "Tooltip pointer leave gesture" below.
+                setTooltipHoverTimeout(e, false);
+                addClass(wrapper, "fade-out");
             }
         };
     }
 
+    /**
+     * Show or hide the tooltip after a timeout. If a timeout was already set before this function
+     * was called, that timeout gets cleared. If the tooltip is already in the requested state,
+     * this function will still clear any pending timeout, but otherwise do nothing.
+     *
+     * @param {DOMElement} element - The tooltip's anchor point. The DOM is consulted to figure
+     *                               out what the tooltip should contain, and where it should be
+     *                               positioned.
+     * @param {boolean}    show    - If true, the tooltip will be made visible. If false, it will
+     *                               be hidden.
+     */
+    function setTooltipHoverTimeout(element, show) {
+        clearTooltipHoverTimeout(element);
+        if (!show && !window.CURRENT_TOOLTIP_ELEMENT) {
+            // To "hide" an already hidden element, just cancel its timeout.
+            return;
+        }
+        if (show && window.CURRENT_TOOLTIP_ELEMENT) {
+            // To "show" an already visible element, just cancel its timeout.
+            return;
+        }
+        if (window.CURRENT_TOOLTIP_ELEMENT &&
+            window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE !== element) {
+            // Don't do anything if another tooltip is already visible.
+            return;
+        }
+        element.TOOLTIP_HOVER_TIMEOUT = setTimeout(() => {
+            if (show) {
+                showTooltip(element);
+            } else if (!element.TOOLTIP_FORCE_VISIBLE) {
+                hideTooltip(false);
+            }
+        }, show ? window.RUSTDOC_TOOLTIP_HOVER_MS : window.RUSTDOC_TOOLTIP_HOVER_EXIT_MS);
+    }
+
+    /**
+     * If a show/hide timeout was set by `setTooltipHoverTimeout`, cancel it. If none exists,
+     * do nothing.
+     *
+     * @param {DOMElement} element - The tooltip's anchor point,
+     *                               as passed to `setTooltipHoverTimeout`.
+     */
+    function clearTooltipHoverTimeout(element) {
+        if (element.TOOLTIP_HOVER_TIMEOUT !== undefined) {
+            removeClass(window.CURRENT_TOOLTIP_ELEMENT, "fade-out");
+            clearTimeout(element.TOOLTIP_HOVER_TIMEOUT);
+            delete element.TOOLTIP_HOVER_TIMEOUT;
+        }
+    }
+
     function tooltipBlurHandler(event) {
         if (window.CURRENT_TOOLTIP_ELEMENT &&
             !elemIsInParent(document.activeElement, window.CURRENT_TOOLTIP_ELEMENT) &&
@@ -854,6 +937,12 @@ function preLoadCss(cssUrl) {
         }
     }
 
+    /**
+     * Hide the current tooltip immediately.
+     *
+     * @param {boolean} focus - If set to `true`, move keyboard focus to the tooltip anchor point.
+     *                          If set to `false`, leave keyboard focus alone.
+     */
     function hideTooltip(focus) {
         if (window.CURRENT_TOOLTIP_ELEMENT) {
             if (window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE) {
@@ -864,6 +953,7 @@ function preLoadCss(cssUrl) {
             }
             const body = document.getElementsByTagName("body")[0];
             body.removeChild(window.CURRENT_TOOLTIP_ELEMENT);
+            clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT);
             window.CURRENT_TOOLTIP_ELEMENT = null;
         }
     }
@@ -886,7 +976,14 @@ function preLoadCss(cssUrl) {
             if (ev.pointerType !== "mouse") {
                 return;
             }
-            showTooltip(this);
+            setTooltipHoverTimeout(this, true);
+        };
+        e.onpointermove = function(ev) {
+            // If this is a synthetic touch event, ignore it. A click event will be along shortly.
+            if (ev.pointerType !== "mouse") {
+                return;
+            }
+            setTooltipHoverTimeout(this, true);
         };
         e.onpointerleave = function(ev) {
             // If this is a synthetic touch event, ignore it. A click event will be along shortly.
@@ -895,7 +992,38 @@ function preLoadCss(cssUrl) {
             }
             if (!this.TOOLTIP_FORCE_VISIBLE &&
                 !elemIsInParent(ev.relatedTarget, window.CURRENT_TOOLTIP_ELEMENT)) {
-                hideTooltip(true);
+                // Tooltip pointer leave gesture:
+                //
+                // Designing a good hover microinteraction is a matter of guessing user
+                // intent from what are, literally, vague gestures. In this case, guessing if
+                // hovering in or out of the tooltip base is intentional or not.
+                //
+                // To figure this out, a few different techniques are used:
+                //
+                // * When the mouse pointer enters a tooltip anchor point, its hitbox is grown
+                //   on the bottom, where the popover is/will appear. Search "hover tunnel" in
+                //   rustdoc.css for the implementation.
+                // * There's a delay when the mouse pointer enters the popover base anchor, in
+                //   case the mouse pointer was just passing through and the user didn't want
+                //   to open it.
+                // * Similarly, a delay is added when exiting the anchor, or the popover
+                //   itself, before hiding it.
+                // * A fade-out animation is layered onto the pointer exit delay to immediately
+                //   inform the user that they successfully dismissed the popover, while still
+                //   providing a way for them to cancel it if it was a mistake and they still
+                //   wanted to interact with it.
+                // * No animation is used for revealing it, because we don't want people to try
+                //   to interact with an element while it's in the middle of fading in: either
+                //   they're allowed to interact with it while it's fading in, meaning it can't
+                //   serve as mistake-proofing for the popover, or they can't, but
+                //   they might try and be frustrated.
+                //
+                // See also:
+                // * https://www.nngroup.com/articles/timing-exposing-content/
+                // * https://www.nngroup.com/articles/tooltip-guidelines/
+                // * https://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown
+                setTooltipHoverTimeout(e, false);
+                addClass(window.CURRENT_TOOLTIP_ELEMENT, "fade-out");
             }
         };
     });
diff --git a/src/stage0.json b/src/stage0.json
index 7a8bf0a80ab..89ad4e0a649 100644
--- a/src/stage0.json
+++ b/src/stage0.json
@@ -17,409 +17,419 @@
     "tool is executed."
   ],
   "compiler": {
-    "date": "2023-04-20",
+    "date": "2023-05-30",
     "version": "beta"
   },
   "rustfmt": {
-    "date": "2023-04-21",
+    "date": "2023-05-30",
     "version": "nightly"
   },
   "checksums_sha256": {
-    "dist/2023-04-20/cargo-beta-aarch64-apple-darwin.tar.gz": "4d98b7d2ed4ff9a73c3d26a45acd113406c122a0d4ced1c1945cbbcefc857828",
-    "dist/2023-04-20/cargo-beta-aarch64-apple-darwin.tar.xz": "3319213011ff4898373894d1ff5c7d9b2dee44cc39c6b0bc69e9736ae5a971e7",
-    "dist/2023-04-20/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "84307f386d3c331ebb43da3b4b7fce61672a32a88ceabfecbd452f0d510eed0a",
-    "dist/2023-04-20/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "7903dd5957bfb2f45127f66ad6bec16bef461a1620ccc39ff44e0566786c97d0",
-    "dist/2023-04-20/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "f383343e236a896ebfa382a5f1ce5087239582ac2d8772625441ea91d08b9f1e",
-    "dist/2023-04-20/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "ece2088b56c5ae2fd41027f6986d16e812b13eda2b0ff3672fbb103d265be1e5",
-    "dist/2023-04-20/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "1766ef8efeed5f606d3ffe6f5a041defb8b07982f83cbc54d134dc278216a506",
-    "dist/2023-04-20/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "492a07d0164f28ba0cd25e2f32d94c800ef106c8f9a39b8253fca05cc33e243e",
-    "dist/2023-04-20/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "44c2d142fd8f1d868e349413e9c072cc518cdf98ab76b29c30eb54feedf39a9c",
-    "dist/2023-04-20/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "3c8819f0ca9e0988c6ca6b8261d1e2c1f37c57af2a6fc49d8b75cffaba835551",
-    "dist/2023-04-20/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "c59ad33dc775892a7465d3e49ff304b7ee105f554f9ba8c7f4bdc9b057b696f8",
-    "dist/2023-04-20/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "8b17731fef0970ee38d1ebd9868ffda44c6ab57a51bac497a36587e49a96f857",
-    "dist/2023-04-20/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "b1e93383e4de4901c1cfa4e85e07d3d5f7e224628df32efd47824dd391c84bf5",
-    "dist/2023-04-20/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "12a4606fc358ad00934cf7dc4b3779c70653acc304d8f4c3ebfd29322a401fbb",
-    "dist/2023-04-20/cargo-beta-i686-pc-windows-gnu.tar.gz": "4a69cda4b23f8482e73f060cb13e71ae16968b9e7a78514ca5c588f285bf8148",
-    "dist/2023-04-20/cargo-beta-i686-pc-windows-gnu.tar.xz": "415929203b23223cb590b37b68b05f27ad84d92b0ee203c26db02da5633b0edd",
-    "dist/2023-04-20/cargo-beta-i686-pc-windows-msvc.tar.gz": "5897a03a62444d6fcc2928afb702b7087b3d6d3ee79dd283b08456857a461fad",
-    "dist/2023-04-20/cargo-beta-i686-pc-windows-msvc.tar.xz": "2c739f9481782515cc4e911686dd5afc5fe839a88fade616bad2c97ac3f5ce81",
-    "dist/2023-04-20/cargo-beta-i686-unknown-linux-gnu.tar.gz": "e9fe240dff59be45f5e9b798e8c05c1548d983ba9356e4f700c50a85fe215f3d",
-    "dist/2023-04-20/cargo-beta-i686-unknown-linux-gnu.tar.xz": "375e787c939c71c15c7286997d2845a3cdf38b614bac9b872886a6b3e92ee64a",
-    "dist/2023-04-20/cargo-beta-mips-unknown-linux-gnu.tar.gz": "c5808c561f5519ff33666dd9457185b3617641e17ade91e6b88b577e2c95f004",
-    "dist/2023-04-20/cargo-beta-mips-unknown-linux-gnu.tar.xz": "24dffb76be37cdd51f69ae8509a7d0acfefce7de46bd1536fe45e7807567dd90",
-    "dist/2023-04-20/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "b5fc64052bcd93154a1da5908a65922ed106b443a8633d8b888b7c5c20bf1469",
-    "dist/2023-04-20/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "813ba9323a1fb70bc04260eb74fece4efb7de88755a1c77dbc9cfda0c9f81f86",
-    "dist/2023-04-20/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "fc67b687248225694f07e4e18716231899cbfdaa2cd74a58460129eb55b47e22",
-    "dist/2023-04-20/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "7f1375c416058e8ac3261d205f2f979986b11cfd020cd5df9ea42c67013a890a",
-    "dist/2023-04-20/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "6296f405cdcef28e877d878ba0e1b9a8555d4a067148b7fc5d8409e39b59b41c",
-    "dist/2023-04-20/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "c22cb99cc2afac88cba85cab7a177361eb98119c3d7748d511112f4ae464c98b",
-    "dist/2023-04-20/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "e30746ab117d9c59a5e36486794394c9279ac4078cd63441efe1bc4843b2e44b",
-    "dist/2023-04-20/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "267f3889a4bfb5caf22132fc6e04ca143240a44a1e8549782e02b287940bab9e",
-    "dist/2023-04-20/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "c6114d5a546c5462fbbfebb092b2b532f3e94a36b1edaa038246f08bc4c05693",
-    "dist/2023-04-20/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "18ef9c3cdbce1e8fbfd50fc41b4b3e45419dfa5bd4f888e64036ca3639c184f8",
-    "dist/2023-04-20/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "c7a511ad37e6bad90b9ecc51cdd74f8c63fca89f0d7c7d639b8770de86cebef7",
-    "dist/2023-04-20/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "45a7b42f9444f3c03b9743d19dfdd3faac55574fd7100372fb9237e2702cb19f",
-    "dist/2023-04-20/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "3e792e4198ea979f3cd572a5d86079594d45e66a40e76a40498a90d3507a4cd0",
-    "dist/2023-04-20/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "6417f9dee2f0f8a96eaac09420eb8906d6d94678404e47f4c5881fc69c43fa00",
-    "dist/2023-04-20/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "95b3116b14643dd7d400a5719865c6b272c84d992e1ab59e292460d82d0466a6",
-    "dist/2023-04-20/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "5d7507e287dfc78b6c526b02a8b2dda940c6953a01dfe0a19c18ce3d1caa0a73",
-    "dist/2023-04-20/cargo-beta-x86_64-apple-darwin.tar.gz": "8b2075a2021b3779b373bb7c0f4243a4830e0d177c486849791aacf96c7c3046",
-    "dist/2023-04-20/cargo-beta-x86_64-apple-darwin.tar.xz": "84da8de65979a9a292bbae1e46478be56fb65b7f85e7e6a7da1a1392494b3f83",
-    "dist/2023-04-20/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "2d8d7c4d7265e1a0b7d845b0d03d73391be2a7bc4ccb00d618a19b86bd7d3d86",
-    "dist/2023-04-20/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "eceeecbaab98ad656d4bd81d770a930d62bcfa800ea8b2272026422433a5791d",
-    "dist/2023-04-20/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "1e00d745fc4c45bc1859527636073b064f66d8050b2d4e740ea3fc0c0ebbd366",
-    "dist/2023-04-20/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "07ae876661f9d58c333ad8bf0d6c93a76a3386c38fa864550afed9fe60f904b2",
-    "dist/2023-04-20/cargo-beta-x86_64-unknown-freebsd.tar.gz": "cad8be555d550b9295b7440ab3cc088c7ad41bc7fe01845bf9daf8362c59861b",
-    "dist/2023-04-20/cargo-beta-x86_64-unknown-freebsd.tar.xz": "b8cf24eeef7d19a26f525bd9fdfc9425524e916aea96f009dc5a885c13789cd8",
-    "dist/2023-04-20/cargo-beta-x86_64-unknown-illumos.tar.gz": "7f58eaaca7b157c82c3631ea15c8cc06bcf273b36acdaf5fcb9099bb88f3050a",
-    "dist/2023-04-20/cargo-beta-x86_64-unknown-illumos.tar.xz": "ba28a88433b3f1a5ad306191960fa1f9a886fb13382b9aaa631c3738958573cd",
-    "dist/2023-04-20/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "1a86221d09e8ef97b3f78c6742159184e5a08420b46729cbaed037ffa999c4be",
-    "dist/2023-04-20/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "9e4e0a0839a87303fca33e245fd4962f4c7ac76e91fafcfc6e918f29f230f277",
-    "dist/2023-04-20/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "e6030829304e60f198647403d00d72402302fd09742dbe75e666d2e3ea4475ed",
-    "dist/2023-04-20/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "f3a8860dd293fbfffe317964df25421b5de2b43db9c69c831084d6d25a4432a5",
-    "dist/2023-04-20/cargo-beta-x86_64-unknown-netbsd.tar.gz": "5bc329ca4bbcd1dff623999177d6bc68043eb9320358da59e935ea6c4bd5eb44",
-    "dist/2023-04-20/cargo-beta-x86_64-unknown-netbsd.tar.xz": "8666cff4e8c4c1b54ad93e202421c008caa33bbc72ef3f9d8e8c4c9d11a495ec",
-    "dist/2023-04-20/rust-std-beta-aarch64-apple-darwin.tar.gz": "d033c430d3af35801bf2ba9ad67e302b71108d5b4a4e5a5f8e55e929451ea65b",
-    "dist/2023-04-20/rust-std-beta-aarch64-apple-darwin.tar.xz": "72d78202353bcaec8ea63c3c41da85a787630d42f1ee1f60df859d08cffe58a1",
-    "dist/2023-04-20/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "338045ac14fb4bd3315075552a0d3ce1ebded292a7601e115ac6b329a36181a9",
-    "dist/2023-04-20/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "59ce7292af43c8af70a4264a76e4429ca07c276a59863902d13c47265defc796",
-    "dist/2023-04-20/rust-std-beta-aarch64-apple-ios.tar.gz": "9cf19d3ce1d48fd59e060c1fdc483ef98d03b34ff81cbe95abb89e6a89db281e",
-    "dist/2023-04-20/rust-std-beta-aarch64-apple-ios.tar.xz": "de6e3ec39eef54f87853609fb747634c3d5e7916274d8f08610d1da318ecbc37",
-    "dist/2023-04-20/rust-std-beta-aarch64-linux-android.tar.gz": "e5385590450562a6057004f36d8b5b2b3e2fa7a04006de54dfbf8247adf12b7e",
-    "dist/2023-04-20/rust-std-beta-aarch64-linux-android.tar.xz": "0e5f65414953dcb7be3dbf556a8da44e0915d33a93c5d62c6f1c8d7e0c32f6bb",
-    "dist/2023-04-20/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "63431ed5bd5037df838f7d7f46118cefebef16393fea2adac7f697775845d4b5",
-    "dist/2023-04-20/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "481bfcb150bee2638336f281cdedcf023a7e65a6f4b8c39255237636afb7d51a",
-    "dist/2023-04-20/rust-std-beta-aarch64-unknown-fuchsia.tar.gz": "16180718b23f1301b45a799e7c7c9e1a0ff83b8a63142d32eb3c07798038ec2e",
-    "dist/2023-04-20/rust-std-beta-aarch64-unknown-fuchsia.tar.xz": "3b0dcc2ea10e8482f49afb0188887b5f17f4404d4f182f8b9e2f852aad220d70",
-    "dist/2023-04-20/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "ed6117f7d0e7bcf9e7ef7a67b2a552ef616cb16843ff44d6d4cb9de2b0145a78",
-    "dist/2023-04-20/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "449daea8f5466e760ddb5b45526486b6386ddd6a546b5d2d589a38d96b2373fe",
-    "dist/2023-04-20/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "2719afaa0560f3974a56eebe24b783b45a0b6022c1830336d96ce9979d58995e",
-    "dist/2023-04-20/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "6eadf7df3987c9a56023303d950779ca24648a7b3408ddd8e492d74210c95914",
-    "dist/2023-04-20/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "a2428f7ceae916c49f54891f85a8db5f7d48748afd9cc121f1bcd58041afc0b6",
-    "dist/2023-04-20/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "72b84200dec649a417317c78f05162ebb8a3325b9c3a582085b0a2bc0de34741",
-    "dist/2023-04-20/rust-std-beta-aarch64-unknown-none.tar.gz": "de5a37cd7aa2b97f693364b3202eb1ef3af57efe510626df536a8e21589ed2f0",
-    "dist/2023-04-20/rust-std-beta-aarch64-unknown-none.tar.xz": "e95b5428f7347ce021d509d64c414705f82800d979dc9e0937f3f7318da1e8f1",
-    "dist/2023-04-20/rust-std-beta-aarch64-unknown-uefi.tar.gz": "869534cf8258feffab97417db638f8e18fc8980fc7f5f47f347fddb1190e3575",
-    "dist/2023-04-20/rust-std-beta-aarch64-unknown-uefi.tar.xz": "9697f68c98a764c7105fefadb35a911e9aeca6cb094134033abcae429fe1acff",
-    "dist/2023-04-20/rust-std-beta-arm-linux-androideabi.tar.gz": "bcaf8f9e3099e77a3389b32f016af7d9faaeb661976707df02d5fc43ba9c1809",
-    "dist/2023-04-20/rust-std-beta-arm-linux-androideabi.tar.xz": "a9553688137f7b345f13fb3fb3a7b57370a6856b513be52752336a8b33da4329",
-    "dist/2023-04-20/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "55bb0e601d0b60f3c6ce434ad527a2fa4eae1c1749c63958ebee60a3b75a78ab",
-    "dist/2023-04-20/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "0e54d080e47693d6de6ad9b3a25a3667754346e3c699017adee94095f31130a9",
-    "dist/2023-04-20/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "6724ca816dbbcb6020ae413de2ff7b6dea7d976eb36e92916700a4e3c9284dbe",
-    "dist/2023-04-20/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "b39ea928a753ee8a66bed531900b2f5526c30c6a959b17aab72580e22027c5e7",
-    "dist/2023-04-20/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "3165943ddcdd9a308e2bb5437b09aacd4e164a345495439d0edab26b497ddf2c",
-    "dist/2023-04-20/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "3e6f52a2e03d4fe56ba0fd7fa4db7ee95c115c678ebd71baeeddb0ad6e08ec36",
-    "dist/2023-04-20/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "8228dbc77321a471bb4760e245d4658459bc89590ec49e459b158d99bc3a043a",
-    "dist/2023-04-20/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "a1699ee7bb2d84a2dfb25b66b8fb926874839c7c5b171dffa5acbdcb611c4cd7",
-    "dist/2023-04-20/rust-std-beta-armebv7r-none-eabi.tar.gz": "a9217cb08456e3bc8806ee7be3ec02c3de9ded69562c65762e574d54322ef9a2",
-    "dist/2023-04-20/rust-std-beta-armebv7r-none-eabi.tar.xz": "08b8ac8409b38da84a56b3f8eb662c805e279d8526b6e5b38205f9e6cd0b93bd",
-    "dist/2023-04-20/rust-std-beta-armebv7r-none-eabihf.tar.gz": "673f4d0984a8f18c921bbad319afc6ec3b8e25e3bdb0c38480cbfcccc1e6c130",
-    "dist/2023-04-20/rust-std-beta-armebv7r-none-eabihf.tar.xz": "0f47b88fa6ac741ce7175357f8e92c7e9b5a1d4a41d364c7ad6c4a0bca18f8c2",
-    "dist/2023-04-20/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "b6574d3da501f73de2837997621772522b175c7bae99d2e8e23353a889889db5",
-    "dist/2023-04-20/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "95e2ce2cfdfaa802acd84dbf8a5bc897fa632b18138c3826357ff84fd3f11f51",
-    "dist/2023-04-20/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "dd61c1c8e55f54d92307444d5db0e092de545046b66cc7205ec93c4e6852700b",
-    "dist/2023-04-20/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "0728bec4717ff37f52736cee33fff9196654b0c496b27078e74eeba2634045bd",
-    "dist/2023-04-20/rust-std-beta-armv7-linux-androideabi.tar.gz": "588af191bbff71616dc2d7fddf3415321114f44d0a8e3fe8a6c522a334010b34",
-    "dist/2023-04-20/rust-std-beta-armv7-linux-androideabi.tar.xz": "29f75c5799f79d7a8d589c069c9897817861388d74e3e4cc02cde8c458b59c70",
-    "dist/2023-04-20/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "252e0e1fb1f91449224ac4fa73eb5b13aa204c1cdf9b275abb05105b289936f4",
-    "dist/2023-04-20/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "e0211b866c7136823b5ab2ab0514411e50666cfa898afa2fc4927c870382bd33",
-    "dist/2023-04-20/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "7c68de890cc95eec9a42a4669972f214a5fa2f6cba552c584015ad1f7b89d5e8",
-    "dist/2023-04-20/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "3875fd0963af34cc7deb643e7b82a854de819aa58b521eb151ae8036967af74b",
-    "dist/2023-04-20/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "be5937a48d7dcacb0c25e733bb83bfe93cdf7acb10fd22f679580a0519f426df",
-    "dist/2023-04-20/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "2c34b67a2dc81af1ccbc582d57aa29eb3372f637093a2c782f82ed89ef52010b",
-    "dist/2023-04-20/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "98cc474e0fb49435fe1650f410b39484e02daf10a82fcbe947112496c30ccdbb",
-    "dist/2023-04-20/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "cf1231ff373492437353ff3e465174524661776ec0bc39c5e7bf6ccafed3cba0",
-    "dist/2023-04-20/rust-std-beta-armv7a-none-eabi.tar.gz": "4ab6cc13a0a902dcc95e590edbff7b6839ae7f115683766a8e1b7f0b20120b0b",
-    "dist/2023-04-20/rust-std-beta-armv7a-none-eabi.tar.xz": "bf39cb32d900a6d5856094ee1f972b560256beb80ba7e5a9b6ca8a0e3c34b319",
-    "dist/2023-04-20/rust-std-beta-armv7r-none-eabi.tar.gz": "ad57ceb9ecd6ea1d0691fda8637a4d756576b6695f4c3c07fde74800bca7e857",
-    "dist/2023-04-20/rust-std-beta-armv7r-none-eabi.tar.xz": "163967e6d9361208efc60931db53a7db5ae10a0ddaf6b27e7d3144d9d0d1b4bf",
-    "dist/2023-04-20/rust-std-beta-armv7r-none-eabihf.tar.gz": "d54a199ff6e803adb28dceb196ff90fb6018f817eb6bda2dc69ad0d14dd6e271",
-    "dist/2023-04-20/rust-std-beta-armv7r-none-eabihf.tar.xz": "252ab39a5c07ea74a4c517318b4ca70f946fd3aff6c379d1f9eae801829d1500",
-    "dist/2023-04-20/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "5d55a83f821547e691f4796761faa19b5d4a20b13de6328f461de92169ade335",
-    "dist/2023-04-20/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "1862d1b76a2ae8684994fe8b9718c96aac9936ea11d9c41f520e24d3e01b718d",
-    "dist/2023-04-20/rust-std-beta-i586-pc-windows-msvc.tar.gz": "545d56bbc00df1a535dd6274bb3e0a1bec1bae5c19632fb685d43dd7f877e014",
-    "dist/2023-04-20/rust-std-beta-i586-pc-windows-msvc.tar.xz": "f239658a666a99838b9dc85732fc94b6ae641df07566c0790ba2876495106b54",
-    "dist/2023-04-20/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "3b439a90c15f0382939c350fc0358e71d68ae49a1c56569d0a2954b6148d6044",
-    "dist/2023-04-20/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "c9bb0f39e3d6178b675ae1b73dc366e7a15bc625384453e796fc1b2fc62d58fe",
-    "dist/2023-04-20/rust-std-beta-i586-unknown-linux-musl.tar.gz": "6016b8ea6bb6b056fb01cef60ce26aaa9155c121dde32815ce5cb6bb3314c9ba",
-    "dist/2023-04-20/rust-std-beta-i586-unknown-linux-musl.tar.xz": "b2cd62404bde5d4c745d31d89c6ac3ddc88aac420bb7625dba4ad6cd91ff6551",
-    "dist/2023-04-20/rust-std-beta-i686-linux-android.tar.gz": "8e078415c424d7462814e338b426d77d3351efa702c74d28444f4cfe27c012ee",
-    "dist/2023-04-20/rust-std-beta-i686-linux-android.tar.xz": "c6844efceabff4f5753648a578aed0feffc946819b1c06c2b9119d208876cabe",
-    "dist/2023-04-20/rust-std-beta-i686-pc-windows-gnu.tar.gz": "ebc118086fd129cda6f7fd830547d6bf6d25c7099130c0a9d97ddd60b7fb4d2e",
-    "dist/2023-04-20/rust-std-beta-i686-pc-windows-gnu.tar.xz": "87571ee1fbeae08b184ae8b3ab7c5c9c3a1678479b878bb007810d2755d67a29",
-    "dist/2023-04-20/rust-std-beta-i686-pc-windows-msvc.tar.gz": "0ab9eb41374b2907a1d7912b427861ce47c977ac9c7a9246d0d2025e907ae055",
-    "dist/2023-04-20/rust-std-beta-i686-pc-windows-msvc.tar.xz": "086b03ce92cfa352855fb73ee19ec6ba2f87508fb48a83a87ba8b4e1c1ac685f",
-    "dist/2023-04-20/rust-std-beta-i686-unknown-freebsd.tar.gz": "562a6b5ac2d177628ff6e6440954bcb9306ece91dd0e18fd9802a60c5a49c9a5",
-    "dist/2023-04-20/rust-std-beta-i686-unknown-freebsd.tar.xz": "d258389bdc1300da58edc6c40904b6e63bef3c0ae0d2b86b115c97d66573cdcd",
-    "dist/2023-04-20/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "35df2bb07444d663b42950316d0257098c7afc2f3ed38586a49b977acfc11002",
-    "dist/2023-04-20/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "10b50981e0a1cd66c45da4c565336d89ff9221c0389edbea8fcf09bbae0ec2af",
-    "dist/2023-04-20/rust-std-beta-i686-unknown-linux-musl.tar.gz": "8ab88821e6431c42e5a2c185ee645f4eeb6bc68c5ed0e6ab958bf08e72c1f400",
-    "dist/2023-04-20/rust-std-beta-i686-unknown-linux-musl.tar.xz": "1bb1b2eb46f93792dabc08a5494de4cb30bcee598ef6e20dd93140e2c23e67fb",
-    "dist/2023-04-20/rust-std-beta-i686-unknown-uefi.tar.gz": "01de016073f34946b0250b99e69c800eb7618c3062e3ce7cf2020725598b42ff",
-    "dist/2023-04-20/rust-std-beta-i686-unknown-uefi.tar.xz": "ab8981777cf708f9ca36123a827eccec73791ac55ec9b66ee1ff760c13794090",
-    "dist/2023-04-20/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "81e08c858cc7ff3d16030673b274ae469e04e225898249dae9f77c9013ad0f89",
-    "dist/2023-04-20/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "e5d1867128653a60659844dc8730e34dc110a0f6d69847a8ea6e2d919567bbbe",
-    "dist/2023-04-20/rust-std-beta-mips-unknown-linux-musl.tar.gz": "b8a3b04ffb88b374d1d4ba4a2314b288c5668794b4901bc7086c7fde30f2f901",
-    "dist/2023-04-20/rust-std-beta-mips-unknown-linux-musl.tar.xz": "fab6780f39862274350244a1abc7f1966c3da3c8fa0690a05db31406ad4cc30d",
-    "dist/2023-04-20/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "970f3eae77c78d27f7ba14c31a594151a95e88cad72af5e0cf9d94d350ba3118",
-    "dist/2023-04-20/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "bedcd164f715442282d353ea083dcd34ce7c872475c6cd134bb572a69886ac9e",
-    "dist/2023-04-20/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "67ca11faca21ddd40e4d3734c8b1cbd53eb614c1904662e45ded35e204f14bde",
-    "dist/2023-04-20/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "e338d2024f636dbaf1b6d9eed1e35f2ae63fdaee0e0e6c6cc8c4bf1f90d0f322",
-    "dist/2023-04-20/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "265c2c2575147d0afa844cd480224e2f2ebeb12290b2895ac996aa5fc849731b",
-    "dist/2023-04-20/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "6a08c02546b350c0b38cc8190cc29abf520990178017ff2cfabf502be9af30ea",
-    "dist/2023-04-20/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "a39233f78f76691f102a88a76608015c9223cabcac455763239d572dc4a7004b",
-    "dist/2023-04-20/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "cdaf45841f2465b7827bb86e493d8e471199f431b1b7ab8afdadabf9ccbabbb9",
-    "dist/2023-04-20/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "2f126f585de6ebd896ff9eee00441a79398ef194a6ff676be6d0f8050510932d",
-    "dist/2023-04-20/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "8b42ae4a31f68f864938365055e110c7665e47efd0c98a60f50e77b7e27e156d",
-    "dist/2023-04-20/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "03332ca367b11151fa3dd17df697134bac23f46b79cdf43c86ad17cef0df06dd",
-    "dist/2023-04-20/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "54e0094bd9000029e9349ce7797921703452ea3d110470ee9a493e4e0127708d",
-    "dist/2023-04-20/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "c51a75587b5c864cf2c6b07f41924ad7bf984e00734c9f94cea978ca21ca1c3c",
-    "dist/2023-04-20/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "13074f9149b35e9f88e869f6ae85f27a65c66ec144755f786bfcccb802fa497a",
-    "dist/2023-04-20/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "078fb778f57d80bd115fb765bc36206776d5d2f121d10e4b62ef0cfed787cb6d",
-    "dist/2023-04-20/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "d1e29ab981fa5d18607bc9bb65661676f296133593d133fb175feeaa4f5374a4",
-    "dist/2023-04-20/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "138f93d88c5cf8fe4e67383c0a4b8c3cd1d51e76a30a668439691ec61943f2dd",
-    "dist/2023-04-20/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "7fef6c1d757716aa08213ab034ef77b7d3ea2b749b37608342c4809c972057bc",
-    "dist/2023-04-20/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "a1c9ebd4322d9215e0391d5c30d3e634e05d23c6689980e7576c591342da0e03",
-    "dist/2023-04-20/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "9d21462bbbd99fd57f236ca82b14656a1429301fc81ee152f9e4029b9749245d",
-    "dist/2023-04-20/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "a332218306e37bd6140f8725b1c377af43f39693c7b1443b247107fcfa4a1a21",
-    "dist/2023-04-20/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "79b4eef0907b0ec275e5b287a97f1fd27407c1906243913963171ae584fec222",
-    "dist/2023-04-20/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "5ea2e0d35c18a7c95c9c070286edfe064d73e5a7ef7c17aa1b08d098518d10bc",
-    "dist/2023-04-20/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "12c91e2f5c04ef34a9da4a1ed25c5e4cc4f324f95a27efe832b2e29255b3bc1a",
-    "dist/2023-04-20/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "8cdd8a51216adca6122e684eeb8bd98aefb70315295eccf2f1e5ec2ea3bf7630",
-    "dist/2023-04-20/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "83fda212d6c189cd2ad9a21e442e1d48656d30165c6de941d4f46b6fef9db187",
-    "dist/2023-04-20/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "4e01f5d02fe6a23c0440e2d59fc16a590ed9e514e933622cb836858b3faa9a5d",
-    "dist/2023-04-20/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "a89a4c5ae01ad7d26df5153fc2919815709a63a17e7fd771a3678912e15865d9",
-    "dist/2023-04-20/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "339f71343320dde6a38a270ad26439f66cbc4da4afc3a72c3133c533dd47f75d",
-    "dist/2023-04-20/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "24d2a176029a4894c1474a099fefd27d1e86af70c2cb35ecee29e6e1c0482d87",
-    "dist/2023-04-20/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "7eb3384ed0a63f2b1566e5f7e87100ba790de784ef5237d3272f9c94db88212c",
-    "dist/2023-04-20/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "6524d41fcc8ebf0e2e7ad4c4c0add45b39467aac153448786b1458f2c56d18a8",
-    "dist/2023-04-20/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "a9cd65f1796163a681c1946782627a1c1f4ecf28df7fbcee56cbbcf6d5b28f15",
-    "dist/2023-04-20/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "d03ccbfc381e6ec9458b6e5a2a6d7638b01b2164e43e50403b89ee9f7d10bab1",
-    "dist/2023-04-20/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "ccf9e75be80ab8a64b13d57483c58eb09c16001a6a44ffa275a0e00c830d8707",
-    "dist/2023-04-20/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "9cfb6b4604433f52dd8f0d1a08e86a000795fed9095148c51b1f81287ffb12db",
-    "dist/2023-04-20/rust-std-beta-sparcv9-sun-solaris.tar.gz": "18cf1837ba56256716f79fd5d53b45a50ecc0c2caa368ab162589904a51e7e31",
-    "dist/2023-04-20/rust-std-beta-sparcv9-sun-solaris.tar.xz": "188b3a51ca73a38e9aeba7adf88b9bd7954e8b479c570d4f6844c43e1aac6a57",
-    "dist/2023-04-20/rust-std-beta-thumbv6m-none-eabi.tar.gz": "826e0eea9d14a3f5b9b1b831e1644f5dd8129480683e1dd934772c860394f691",
-    "dist/2023-04-20/rust-std-beta-thumbv6m-none-eabi.tar.xz": "0fd19cc21dc6efce2caa2244fa39f5562fdfebef5f423b4e58d790c1f66de44d",
-    "dist/2023-04-20/rust-std-beta-thumbv7em-none-eabi.tar.gz": "8498c8ace2c28dd06d0c3528759549f3075cb8b6f2e846db479eb96b43a21b32",
-    "dist/2023-04-20/rust-std-beta-thumbv7em-none-eabi.tar.xz": "259b5f0cf679561cf81ef801815ae89c2848232336d6bc5bc8ea06f9ea8d13e2",
-    "dist/2023-04-20/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "6521e7eb5dd003862685dcd19bd6b8aac3ebca54e945846bb061916cb5a8c100",
-    "dist/2023-04-20/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "c2c7102b9135cf63e988401740dd9f0e47d0f6bafa866475ad65d8c2e3a5a6e4",
-    "dist/2023-04-20/rust-std-beta-thumbv7m-none-eabi.tar.gz": "c0cf188a9830d7992796f5b5f5d15d6baa0b94da8575f9992464e8d8811e7d4e",
-    "dist/2023-04-20/rust-std-beta-thumbv7m-none-eabi.tar.xz": "ee37f54d02e22c238d21454ee678b5d349b6b86160a97ab4ba9e348822878b8d",
-    "dist/2023-04-20/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "88d087e15f8a9aff522fa30a7b461bfdcc8a14a1ad22d874727823e8f1dbcc1d",
-    "dist/2023-04-20/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "90f370a2d93866c4a465ad4f7363c46b71f0e7eceb538be0761548447e46b143",
-    "dist/2023-04-20/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "032fe22201db120cb3f95e4f4ff96fdc09fe72b3c023dad19161c94b1bf49b4e",
-    "dist/2023-04-20/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "a2f661de0a9287bd5fbd8a9bbc2fe971d6d0f3e0e33d367339231e788779edd5",
-    "dist/2023-04-20/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "fc8fe009d76071b5a567a5dd6a2efd3daace2acc3cf358242e24c30aeba8e8b2",
-    "dist/2023-04-20/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "6220037537a32841f3ff5ac551b28d85eed3ec2d4a8e9e6d833dca6493b33fbe",
-    "dist/2023-04-20/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "e0f3ae6ea1bf62a5c875ed3d7d0146ae5d7d56826ac1e447a19ec90e564827a5",
-    "dist/2023-04-20/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "796f4b094c1c8df7189584a92158ca8ffc05e4a1a0d3a4d0f8a216bb99bc1665",
-    "dist/2023-04-20/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "65a74d18cc2597e012fbc7800f2b75e16082afb197c680e89f1007257fd114fc",
-    "dist/2023-04-20/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "c6480f3d6cdd2d2ef43d27e103cb894843239f9c2570f9b73afa0d75536dc4af",
-    "dist/2023-04-20/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "bedd0f7d8bd141dc9239484f9fbc2898863097802683652bcb7c59ff812fde9c",
-    "dist/2023-04-20/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "af3121db2d2d98da862e923ccd315af5e4c72f5fcb42b7ece712db8ead615be5",
-    "dist/2023-04-20/rust-std-beta-wasm32-unknown-unknown.tar.gz": "fb9b55a54528fc8894a915578a6e5c3f17e5253355154af48543488da16ac407",
-    "dist/2023-04-20/rust-std-beta-wasm32-unknown-unknown.tar.xz": "0b28eceb3dc40e9de08a9ee6ba781a052b0785ac42b3e6583a6a084332d8993f",
-    "dist/2023-04-20/rust-std-beta-wasm32-wasi.tar.gz": "b801aff4b972011b14b08952f2ea9cb2e12262f50c7c916dbf0a20744b7d3f19",
-    "dist/2023-04-20/rust-std-beta-wasm32-wasi.tar.xz": "26f49c2b5f77404881b9ac6514b9c0a9a49b35515a841c203387cd5e007fda2a",
-    "dist/2023-04-20/rust-std-beta-x86_64-apple-darwin.tar.gz": "23788d725fbeb6055ae38389b7c8c81461fab9f11ac64b39383d2c358ecb83a5",
-    "dist/2023-04-20/rust-std-beta-x86_64-apple-darwin.tar.xz": "d6299ca57f4e2fdef065724507a22ba63bee76fd4fd1c475bf66be2efe396912",
-    "dist/2023-04-20/rust-std-beta-x86_64-apple-ios.tar.gz": "3e1d7c5e728c306d7697564d512577d7f2b0868c3bf4cddca206948b9ef676ee",
-    "dist/2023-04-20/rust-std-beta-x86_64-apple-ios.tar.xz": "a34a5a4a8fc36501a3511a34721c68659098d985e7516e1fb30e2ae9ebb13697",
-    "dist/2023-04-20/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "fe046c71f7a09a0a4eb4b023756c6b751afea7092e7f4b53b6321c593dbf6e34",
-    "dist/2023-04-20/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "b4f482c9cf11bb1ae253cee16ec90748d2327733b6b9a0b32d68a16cea99974e",
-    "dist/2023-04-20/rust-std-beta-x86_64-linux-android.tar.gz": "ca160d9645ebcaed94e742bc4d2a70c026c5cc505c00ed0feae406ab5eb2ea68",
-    "dist/2023-04-20/rust-std-beta-x86_64-linux-android.tar.xz": "764c2cc73a77c754c84752cc3ff9f6369c7ff2af0bc8c3840aab20bbabae7d79",
-    "dist/2023-04-20/rust-std-beta-x86_64-pc-solaris.tar.gz": "bc3159503789a508943b5e5a1fd4199fec023b448da52ddba517a9c748d9fdb8",
-    "dist/2023-04-20/rust-std-beta-x86_64-pc-solaris.tar.xz": "2d43fcb2748fbec913001f880e1b279a3d854b6203694acf513bde0a3c172fc1",
-    "dist/2023-04-20/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "1385f3a1468a4d30a7b4d58d4bd683656bc1191ba7371ea4172a868a15af9343",
-    "dist/2023-04-20/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "d7e4dded34cd043c411dc6d78463442ee02545610fb34b050afd4b453f8d3328",
-    "dist/2023-04-20/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "eb9181a4bc3d7e02aa4fb959446894ba8a3efe4e71dfbc3e7b1ede6cb52ae87c",
-    "dist/2023-04-20/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "1b23632345f55cccb9fbc47efdb8f8c9fd4bd0172fa21dc813832a9bcf58f75c",
-    "dist/2023-04-20/rust-std-beta-x86_64-sun-solaris.tar.gz": "8edcf15812bb2726d5a0efce4e8e49d442c91c26fc35a26a76993aedb7a514dc",
-    "dist/2023-04-20/rust-std-beta-x86_64-sun-solaris.tar.xz": "8050ae692ee600cd5beedcabb2088e7c1f7f222c85abda5af289861a550c1a21",
-    "dist/2023-04-20/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "7f820b5362c8ab6d52a3d54689383cad76db2bad351fdbc703c0ac25f2fb2f41",
-    "dist/2023-04-20/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "d22641d071a0d07206300cbdd0024ca49b4fa95635c6b5477114119421cacef6",
-    "dist/2023-04-20/rust-std-beta-x86_64-unknown-fuchsia.tar.gz": "f27dd55f65b30f5528d1ecd53209435501747a6dc95940dcd193b0887befb635",
-    "dist/2023-04-20/rust-std-beta-x86_64-unknown-fuchsia.tar.xz": "5298fcba18a6a74f39ea5ef356e2b7af6a605c1bc988bf3808f188ac331231f5",
-    "dist/2023-04-20/rust-std-beta-x86_64-unknown-illumos.tar.gz": "74e6f11ae802eacd6ceec24c349167919fdcdc12645b0884acd3a97f8dda29bd",
-    "dist/2023-04-20/rust-std-beta-x86_64-unknown-illumos.tar.xz": "28aadd9024dd2caad14bcbe18a917d72bc5c6336e3498c2622c361086ae4f357",
-    "dist/2023-04-20/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "050e31339de130c68c1f20403a95140aa438f1254c56aae5f3525ce6b610fbcd",
-    "dist/2023-04-20/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "f68ffe728f8317f19ea1431542803c2800272174c003b6a8c2f3d2f12494c20d",
-    "dist/2023-04-20/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "1355d05d311e6380bc1d40b23c3f4d8cdfe5b41f900ca1025b7bfce309cee2f0",
-    "dist/2023-04-20/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "f6441f808026691def0f4909dd1df9ead77d2698ec44fa2627110aab271ba44c",
-    "dist/2023-04-20/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "c11b544ad540c7d0ef1fc4b09bfa7219d738b214baad0de961ddda011ea88a6d",
-    "dist/2023-04-20/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "9fdaf1c1f1fc26bede80b9dbd3c86bb5e9d528a9b94ae9185bad6bb9b56bc7ab",
-    "dist/2023-04-20/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "809a1a05f2367286e5bc22c2b963cb0c6216af552f7f16ff460776fc87b64147",
-    "dist/2023-04-20/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "ead16d54ad9b75957396b9294c11289d2580c48e3a270ab45bd7ed4462065767",
-    "dist/2023-04-20/rust-std-beta-x86_64-unknown-none.tar.gz": "b5791dd97106c645c4d36255fecfcf917c80ecb59d12c06e74f89cd7cdd81ae8",
-    "dist/2023-04-20/rust-std-beta-x86_64-unknown-none.tar.xz": "15eb3115d973d298a2994bc9ea2c9c34dcc8c220152adc85618a4ef8892db427",
-    "dist/2023-04-20/rust-std-beta-x86_64-unknown-redox.tar.gz": "afb13c0ed02115605d4f5ffc303365604463ff1a6e63c4f1a8b7c5d7975db2b0",
-    "dist/2023-04-20/rust-std-beta-x86_64-unknown-redox.tar.xz": "f8b8d606122dbaded0219c332b2c8f440356af559738bfe98072f5cc6460d057",
-    "dist/2023-04-20/rust-std-beta-x86_64-unknown-uefi.tar.gz": "591a861e52f362b5ccda9cf4bb658cf9731bf03e992de3a7a176ac0d282bcfd5",
-    "dist/2023-04-20/rust-std-beta-x86_64-unknown-uefi.tar.xz": "8017eb935b1fa3fc84bd0f02b30076f4c8317d5a0249461f095336139457a03e",
-    "dist/2023-04-20/rustc-beta-aarch64-apple-darwin.tar.gz": "df30a906559e5fe0ffe481e6c53048e11cded36299dd5e208cf43ca10ccb0c89",
-    "dist/2023-04-20/rustc-beta-aarch64-apple-darwin.tar.xz": "2d5310cff690739cb0ca63b1f8ee91f7cac09a3f3459bc877660b1f29821d4c2",
-    "dist/2023-04-20/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "12cfd51bf114a9d1fda6a4b9853bb77412c55a75b98212758bee39dad0426ea0",
-    "dist/2023-04-20/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "bb638a2efd4a2069d692986a4d5664f9aff3e1b446691b4b119517d339d98145",
-    "dist/2023-04-20/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "b3f9a0f6ddff10cf023b7ef8cab23663199e0714b9315e339f73a3de7f3064a3",
-    "dist/2023-04-20/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "f6daeb04ca076a552a7b985f87cf82a85d41c1e293d05d3991987df1924f748a",
-    "dist/2023-04-20/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "4415af9650a37c4f88430679f8647b94bfa731b71355a8bf1144a15c5b0b0944",
-    "dist/2023-04-20/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "2022d75946b1799bd62b17dfe216aca86eaa28528ddc226fcb4e88d82d443ec4",
-    "dist/2023-04-20/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "7a94b768ecc665c3d9c4d093ed3b8d7912e38246646540ea57b9ef7b013fad92",
-    "dist/2023-04-20/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "e5ca6d324efc9b1eedb307d3e425c4811d62d46102ea8ddd72c39bf2f3c789ab",
-    "dist/2023-04-20/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "94d1602c630a92ffee62e7ab6acc3a3bd9475e90482658e97bbc6e1072f60a87",
-    "dist/2023-04-20/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "50c3bd42c30c5d3eb7a79ec0c977736391803a2ca3f00bacf9593899b1dca9fd",
-    "dist/2023-04-20/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "c60a9bcdaabb7c7420740a1e4480c4927277498bed34ffa5578c85bd5158eaab",
-    "dist/2023-04-20/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "a837407a2338986e23479caa752056746f5b6cca4c90f08c0f31eb8aaf8a4c45",
-    "dist/2023-04-20/rustc-beta-i686-pc-windows-gnu.tar.gz": "46eb4e2a617ba1cdb7964a1b5678d977d486883deb13801c7114359c5c73c8db",
-    "dist/2023-04-20/rustc-beta-i686-pc-windows-gnu.tar.xz": "c6f2e7912736e467c99c0a96041c77db1bcbd22b370861dfc599c37a04606456",
-    "dist/2023-04-20/rustc-beta-i686-pc-windows-msvc.tar.gz": "58487cd26b0bd63ff5a55aeafa5263dc9973267a9a1bec0d3d75da5dab83e34d",
-    "dist/2023-04-20/rustc-beta-i686-pc-windows-msvc.tar.xz": "700dacd476ad96ff0d4e3d95700d309eec8d4d6f25fcaa75c096d31890a86f4c",
-    "dist/2023-04-20/rustc-beta-i686-unknown-linux-gnu.tar.gz": "5b1c00b59e65da0d1ef324d8cb7ac2b4d2467d48747aa20013ea32385ae7b110",
-    "dist/2023-04-20/rustc-beta-i686-unknown-linux-gnu.tar.xz": "b9f08288717c10a199847fa8a8881db6150f4bd041b6fe5fc3522bfcce66994b",
-    "dist/2023-04-20/rustc-beta-mips-unknown-linux-gnu.tar.gz": "77c6117d251e2ae8ce7490c2883ce70f93bc82422c727c0440e0a95e1567d1b2",
-    "dist/2023-04-20/rustc-beta-mips-unknown-linux-gnu.tar.xz": "b6e6e946e1e0c23c40f36fb290be44417e6d20cef97b5b52093a127ed4bfdfd9",
-    "dist/2023-04-20/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "808f0678511d2b0028e563d13370978538fa5017886f7f7a6f4aab3cf980cce3",
-    "dist/2023-04-20/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "f57673de409033817dd28ad563ae55af7605ffd6764e08b8ad7edc3ae2a4371a",
-    "dist/2023-04-20/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "9466f0b8816eb4579186f4bf0dc16c97171767df42779ce227df115ce6dc9555",
-    "dist/2023-04-20/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "06b768bf4c0c359a10ee937943587a5a37c32335fee3d4276114c4e3f6828ecc",
-    "dist/2023-04-20/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "f4ff7fc2dadaa65b8777e147e46d176f1b8e1612f060ae5c9547f3ccb3515391",
-    "dist/2023-04-20/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "21f6553daee7f77d50d70a8b5950de0a4c7c06152637db5eaf42217260f2d79b",
-    "dist/2023-04-20/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "e8e5a6f5c9ec807f2f4e4c0944244c81896793180614cfd6bb1181d50a70fb3e",
-    "dist/2023-04-20/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "5de90f98ee29edd5d1d7a2de216571c23ada154d913dd03f218caf8bb23682f9",
-    "dist/2023-04-20/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "e91270ea9b83946e7f4d267f8bcff0a3670d070bc87abb1e27c161db832f1965",
-    "dist/2023-04-20/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "0ebf2ce2ec6c892be3b010d3d09a46fc0d7a23a77485aa8ab468444fcfc7bb08",
-    "dist/2023-04-20/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "7a40bba3c68766a184507c9a378a1e4ace9745f065d0409519e9fbad57dd48ee",
-    "dist/2023-04-20/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "8b1187e4a089b66e9487b791b4a60850eb57c6c452b8a0c745d24715ac44956e",
-    "dist/2023-04-20/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "550fbced66a230358f8d55b9b204e737bb3bed4bb8ddff844adf598a6b2bc54b",
-    "dist/2023-04-20/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "ba68303e8f056b800884b50f477544ba15374defa88d174174f1a8a8a14a589a",
-    "dist/2023-04-20/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "d734fb85d633662a554bd2c72b7adb36d904951fa9bb48194a092b35b5d36ef7",
-    "dist/2023-04-20/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "ab189b6ac12fde284b4c0357b864dc4846c805a39c9d5a4049799d08323a6820",
-    "dist/2023-04-20/rustc-beta-x86_64-apple-darwin.tar.gz": "b3f56d905276e934772709e270ebbb13faa8301cc92207e061adff917310a370",
-    "dist/2023-04-20/rustc-beta-x86_64-apple-darwin.tar.xz": "190e0e338dd39326ff7835dfd13bf2b53355c5a71f0b63df0e2e822997f7ef6d",
-    "dist/2023-04-20/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "68e286df51faf067bba9c4c10dc6ccd4e6b81d7c2bb1487960f57d9ff18c1e73",
-    "dist/2023-04-20/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "28fd89783bd2023bd4ef052d7ac541772ed39b51f87838806b80ec493f35da10",
-    "dist/2023-04-20/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "0072d99adc95ccb1922137a6060b1aae74142e0a8343fdd459a772502e0a34a7",
-    "dist/2023-04-20/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "32839a7cc46f066681bfa5c8609ddfb473813e7771b363f194d061d8d886c5ba",
-    "dist/2023-04-20/rustc-beta-x86_64-unknown-freebsd.tar.gz": "b3b10e6eb7c7ed578418f42058e1d5b287477a1a95a3d1263976c8512ed93ab0",
-    "dist/2023-04-20/rustc-beta-x86_64-unknown-freebsd.tar.xz": "6f65d34f49d87a59c82464d6c045f346a6797e2795fb9e31223b09fe64f60c9c",
-    "dist/2023-04-20/rustc-beta-x86_64-unknown-illumos.tar.gz": "83a97feaab58ec2997a96f902ac45cb8a0d8d307bc8e3c7a7d2e7a6cbe0df1cb",
-    "dist/2023-04-20/rustc-beta-x86_64-unknown-illumos.tar.xz": "18b0611345a6ff33a36d1f19f175dc9b7a8e2fafd9e84ef95fd9978b74e14bb7",
-    "dist/2023-04-20/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "c64fc2556a68c3a775d844478e8ab7f46ada112474d965ebb917ed033cffe48b",
-    "dist/2023-04-20/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "cd24c2150f618aeff6287d99cd8623f55f766db0d7b929b9263666c86a71d2bc",
-    "dist/2023-04-20/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "208dec1e29ceea4bd35d54476f9c57228598eaf98bfec823e19386ae476f231d",
-    "dist/2023-04-20/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "a205bd7ac479b549c23dc6d50e49c603c93289d8987c2c87fa46a430b7392dd4",
-    "dist/2023-04-20/rustc-beta-x86_64-unknown-netbsd.tar.gz": "b55315862eea659a2c4b1c1a832bee5e56ab789ac62618e746a2ba3ddeb13023",
-    "dist/2023-04-20/rustc-beta-x86_64-unknown-netbsd.tar.xz": "f67e17d9d9b98ed126a6b4b3c2dc86048fc96187fd26cb9f1fc5fb5269bdea05",
-    "dist/2023-04-21/rustc-nightly-aarch64-apple-darwin.tar.gz": "b14dc1f1473ea109907787a1886b4c0f89359957dbca6accb3ab6ee1cf1aa64c",
-    "dist/2023-04-21/rustc-nightly-aarch64-apple-darwin.tar.xz": "cd8a5b832c0a54d23f82dcc556bdcb387ea0f761deb2502e7b952923bc0f05fe",
-    "dist/2023-04-21/rustc-nightly-aarch64-pc-windows-msvc.tar.gz": "8b1ac2260179d455896659e04bd282a57db1e43638ea7d305ebdca8007b9a89e",
-    "dist/2023-04-21/rustc-nightly-aarch64-pc-windows-msvc.tar.xz": "748af05581d719e3aab0f0a75391979c9f15f7c0ee37bd8244051b5d00632d32",
-    "dist/2023-04-21/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz": "c60938505082ca3d0d581b2749aa53792b63e9061ae80be0addbdc2367ee07e9",
-    "dist/2023-04-21/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz": "9f0f3f4d332b5d106b4fb45060fe71f9cec973cfed8169d6279644ab5d37cdb7",
-    "dist/2023-04-21/rustc-nightly-aarch64-unknown-linux-musl.tar.gz": "f211b27640ab0b9a2aa6275d3dc4f11749beee4f48ada3df723c27214d0048a0",
-    "dist/2023-04-21/rustc-nightly-aarch64-unknown-linux-musl.tar.xz": "2a4355f91f3a5ee31e41905740541504149ec4045a7b806017d869cf00453d0c",
-    "dist/2023-04-21/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz": "adc2537aeb691226d10d1b306805fe6e9b96461df33854917f33018569968af1",
-    "dist/2023-04-21/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz": "1bac0bfdaf8f538099b7551225ab18754a5457cd89d1805368b3bbb583cbd9f2",
-    "dist/2023-04-21/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz": "e98227f4396417d72889d1ef9d073cd81668539e24691b2803f877227341a7ee",
-    "dist/2023-04-21/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz": "e9d6b6e35164da9b2c7adf474178e5263e79acd65a9f020cc3be16d55f5eb511",
-    "dist/2023-04-21/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "4a5917e4bd3eb6210903edbd5551426911141768b6979d59eef53b36c125ad3a",
-    "dist/2023-04-21/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "dcc87e08210dfaa4629bef68f71464b8b81bbf9e7180d9d385a2c15b06b7f18d",
-    "dist/2023-04-21/rustc-nightly-i686-pc-windows-gnu.tar.gz": "4252bf99e0738dac18e51f0c7f4c3628ead5909222d18b3b7b780b90062aea7b",
-    "dist/2023-04-21/rustc-nightly-i686-pc-windows-gnu.tar.xz": "150824f08e818b6b1485823217056a2d568c803e63c9c753fb11cf93b4de6cf1",
-    "dist/2023-04-21/rustc-nightly-i686-pc-windows-msvc.tar.gz": "73de440b9916a3ce442501dd15239184a11f47e17fb2d7e3943af2c0ccbf9f1f",
-    "dist/2023-04-21/rustc-nightly-i686-pc-windows-msvc.tar.xz": "8fea649215bfffa876143c91ff4fcddfd6c5305bb05d4f8656766fc63c1a19bb",
-    "dist/2023-04-21/rustc-nightly-i686-unknown-linux-gnu.tar.gz": "07484b9e5c9bd6fedf24999fa3350f3efa3e04da99a4bb7d6e51e27b296a1833",
-    "dist/2023-04-21/rustc-nightly-i686-unknown-linux-gnu.tar.xz": "2440021d923189b5bfa789d0714e974707750deedc9dac79da7c41896ceb210c",
-    "dist/2023-04-21/rustc-nightly-mips-unknown-linux-gnu.tar.gz": "2d0b23098bc0cfa680234fb3440908f88a075d91da8a489b8da043dcfdb8d361",
-    "dist/2023-04-21/rustc-nightly-mips-unknown-linux-gnu.tar.xz": "39b47607fc849cbbf80ca89881e7440e00ec2b0af83ec6274dd0d4723f960dad",
-    "dist/2023-04-21/rustc-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "bf7a8a1f9a712604072baea92f8637fc44b8b33796d187a9ef9477d142f0c2a6",
-    "dist/2023-04-21/rustc-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "df760912c668f6b3b23607e97f6dfbeab9d29357293d31becd41d842debe866a",
-    "dist/2023-04-21/rustc-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "4438e9f19f8dccda2be4911e20a99cc4fcd3555282ea40f363d75ac96133b9cf",
-    "dist/2023-04-21/rustc-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "e9085975facdc36f0a133d6e9a6726a4322848b833a72a5bcf54e438685d0a50",
-    "dist/2023-04-21/rustc-nightly-mipsel-unknown-linux-gnu.tar.gz": "8e4ae9bf1ee6743b8783c5412843b587bab9b9bd67d02b2f919e6dcab770e221",
-    "dist/2023-04-21/rustc-nightly-mipsel-unknown-linux-gnu.tar.xz": "af6a21afd7ef9d9735c58bf797a3bd2c6eae41741c37395a81b9238a1f37c1d9",
-    "dist/2023-04-21/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz": "e9ceb40b6d389526b72ca08dbdc035603e307b18b41e070564ee20ae15105cab",
-    "dist/2023-04-21/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz": "7f30002cbd5c81ccebad47cd8129df88391c12a19f44626a0776f8093f420a24",
-    "dist/2023-04-21/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz": "e710bde14522bd4a24e90e6d274d7293fcf47e29d432910f206bbf024652d073",
-    "dist/2023-04-21/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz": "47730b4838b7c6e28436174bc5835d966af0a3a9f4f1180e160ca030cd8009d4",
-    "dist/2023-04-21/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "b6c969e1b6393a0749de17b930313df76f64024a5ff68e4a5d7ab182a2c39fd5",
-    "dist/2023-04-21/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "1530809f81bf2805415980148678a12f680909d439ac440157c6ba5df64e0d7c",
-    "dist/2023-04-21/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "690a283c9a3db2b3234aa5fc7828df2ce2901fdd72db10b35e8234c3df8520f8",
-    "dist/2023-04-21/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "531f4ba41edd1de2b27ee8798a5e8f5e3b5fc1488d743e5020d29834cccae273",
-    "dist/2023-04-21/rustc-nightly-s390x-unknown-linux-gnu.tar.gz": "ad454aa9437687fae9617f84d921489ce2ea8e61e5c2e50b3ec13ca026c0d515",
-    "dist/2023-04-21/rustc-nightly-s390x-unknown-linux-gnu.tar.xz": "9cc9a96848519c8c80cd44d14760e49b0b92cfaa851db55c5b1c7f7bf9fd95d5",
-    "dist/2023-04-21/rustc-nightly-x86_64-apple-darwin.tar.gz": "1c4ed2e08ee181cd9d28fbd0cc4b5c0c73d8e6a377c5ab6b4849e0ad8182a729",
-    "dist/2023-04-21/rustc-nightly-x86_64-apple-darwin.tar.xz": "25efab0032ce61d70abeb9f3053a089f827ba693c0502df2225939e8f77184a2",
-    "dist/2023-04-21/rustc-nightly-x86_64-pc-windows-gnu.tar.gz": "bec16f18e79a32f304c17811baf64ac1a8149a15504c7bb5f3d198cfe09db6bc",
-    "dist/2023-04-21/rustc-nightly-x86_64-pc-windows-gnu.tar.xz": "709fce3891b9688a05d7e7dfbb9cfef15ad6461ce54923e06b2dbbcf87ab9b57",
-    "dist/2023-04-21/rustc-nightly-x86_64-pc-windows-msvc.tar.gz": "15704e62bad40fcec9a14bda6f6d11419970f1d050aedbf4157f1f26cbec45cc",
-    "dist/2023-04-21/rustc-nightly-x86_64-pc-windows-msvc.tar.xz": "7f5f8fd10c2068a7d1bff3ee9bef92dbe9a11638b7546ebb8864058b7d1efdaa",
-    "dist/2023-04-21/rustc-nightly-x86_64-unknown-freebsd.tar.gz": "1302219d277d6625b0bde7768e78f2dd285d47a8de928eb2c767b4b9e20f11ed",
-    "dist/2023-04-21/rustc-nightly-x86_64-unknown-freebsd.tar.xz": "51311fc67fd86ca7baa0601ac2f1d53a4dc4671132c190dd305f96d6bec47a40",
-    "dist/2023-04-21/rustc-nightly-x86_64-unknown-illumos.tar.gz": "2409082de839f235c9dc1b8366b1060356f708be2476e72aa3a911abd9b46542",
-    "dist/2023-04-21/rustc-nightly-x86_64-unknown-illumos.tar.xz": "98c6da8aa7783d3b078240133d0446b99277a5721ef8ec94bb56735fc444eba1",
-    "dist/2023-04-21/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz": "7703bfcbaa7dbd99175101fc5a9c99556fdd556b77f107c3c0e89aa5c78e2479",
-    "dist/2023-04-21/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz": "30704ed5b752bf574e3b149056f033ff2bf96f6841810c2adebc5c5e52593002",
-    "dist/2023-04-21/rustc-nightly-x86_64-unknown-linux-musl.tar.gz": "d46394234d911737ff913dddc4697d352e291dd8f9b9e39a1ff92e0a6292a0cc",
-    "dist/2023-04-21/rustc-nightly-x86_64-unknown-linux-musl.tar.xz": "d6a8a6bbdd8fc0e97f455bd7df71c1bc5ea0230b7894af5beff2e76880fef1bb",
-    "dist/2023-04-21/rustc-nightly-x86_64-unknown-netbsd.tar.gz": "701fd848e1529d39bd2d0b0aab40b20d2259e9f57dc40f4bf77c1d45bd894d25",
-    "dist/2023-04-21/rustc-nightly-x86_64-unknown-netbsd.tar.xz": "ec6bea58a1b0788391ea57107d3c78734328c47f5b91edb92996d64a8b5f8bc8",
-    "dist/2023-04-21/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "66dd75310abe0112d3ef75345a0f3054ff936ea7098a040d20cb8968b7d1b2dc",
-    "dist/2023-04-21/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "705d9dc8548dc84ba9c69bf5935860658ae501cf577584610974b4448ba7588f",
-    "dist/2023-04-21/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "b4d2541fbc41a5b9fbfb6bbe8a869eb8794d658ad100fe402c4c3ceea12cc824",
-    "dist/2023-04-21/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "d16338308c83de20b9f86e56c83f9601fb3ce3b7f9be26d9210f401319786ee2",
-    "dist/2023-04-21/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "b8300c62cbf2136b86fab4ba1357ede3b4be997262844bae7cf1694b250a75f5",
-    "dist/2023-04-21/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "6979a86d568e58fa1295fefe71007d374a2975ab10773af7a2f2876ad2f2773b",
-    "dist/2023-04-21/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "74ef4daacace0d036148f5dad87e759441925b1882da2bd6fa2f8628a290edc3",
-    "dist/2023-04-21/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "6a35624795fc157d7587bf4606698c471ce82c2f12269741cf5d414e91ee4b6e",
-    "dist/2023-04-21/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "7d4914fffa7ceb97c8e16969c9f2072decadaedea658bd51d6590a6caf2b53c2",
-    "dist/2023-04-21/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "5df0c332bd3760c4da08d4cd330e3f2fc865f9f0b11b54fd7c7c41fc56f582ce",
-    "dist/2023-04-21/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "2ab4f71ff23e68923e24ce906f387bc1b6c00f07e1ed13492516c14b652936f2",
-    "dist/2023-04-21/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "bef7cb9b4dd0bdfbba20afe603d60aa37df77ba6aa8e179a27a0a46ce9febe9c",
-    "dist/2023-04-21/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "adbf12810a829d35e85811d5fb715012434d99d42f88340ae61a9141bec9ba95",
-    "dist/2023-04-21/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "242205fe65d10548b69a7520b33ab6584248817454f19c3da1328044c43c2260",
-    "dist/2023-04-21/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "2e720a30089b192f4bad517600544c9085a5b8ff0a3afcf7d1b1a8149eba5af1",
-    "dist/2023-04-21/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "7a2c5a01cb6a47d86ef02d3bbbc2b7d5b1f2eef68cd4aee00f3566accfc429e2",
-    "dist/2023-04-21/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "f7e1d6cbf83508a0e3c06090fe80ab314299d2ac24be0f8e3e5658177e270a0d",
-    "dist/2023-04-21/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "630bbe6d526774effd0602ec17eac0d4b5d00e67402fb189f282416dc614a3a2",
-    "dist/2023-04-21/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "47e2b997cd75a8e1efd67bed1f0a3e3255cedffb542bc8eb3da695cc819d5684",
-    "dist/2023-04-21/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "71c07ca9546a8e404da5e2024374876e3f282aac54f04076c26dd4f3f53d79e8",
-    "dist/2023-04-21/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "2131b14553e7f3cc276410a6e3e3fe309a12a65ce8dc287b2bc543d1c1769122",
-    "dist/2023-04-21/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "8ad25a066126b1b0485cbae336f0350c6b46e4463fbc9593916c495875b5f3e9",
-    "dist/2023-04-21/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "a5231553b80b57703988099f4c466a60e4b8d13cae9e8e25a3acfb5c59e3d493",
-    "dist/2023-04-21/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "7da93b04275989b6917e5538d0f2591ecce0c87bf78c4fa79ec24b262fcede12",
-    "dist/2023-04-21/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "ff173fb7a5b2884963890c4a5728c3766d89d6d68e823d9d0f026e4b47c04adb",
-    "dist/2023-04-21/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "23f0af9943a0d5f97e61258e5f75b6a0542a9c6ccc9919f083e3d331c154b55e",
-    "dist/2023-04-21/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "b6610919e1f96cd101d1170541b9ffec0a5e617760cd1ff221e1aa163bbe96d3",
-    "dist/2023-04-21/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "6f17563141a1153b5b2e489925336ef2d52fb3db66a081f818e475ce03a8fbce",
-    "dist/2023-04-21/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "9596395db964723ad81b790b6ab8cde64584dc6fc672bea5a0f77388457d385c",
-    "dist/2023-04-21/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "eb0175964c23b792a20e4d7e086d97a857842982a41f9500462851203c9ce54e",
-    "dist/2023-04-21/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "5681022c372dd95afe8751b0eb1a4085d2b47163c4858744f80381d47ee113fb",
-    "dist/2023-04-21/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "cd3b6d0d9510eb99e7cbaeb8e947ead7f1a8456dae4e7b727c08b3b4510bda4c",
-    "dist/2023-04-21/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "8e6329116e796f8f26921ced59ff28040f23773b0b9db8b2ac8519c779703c23",
-    "dist/2023-04-21/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "7850600a2ef836e47b0a3fdc33e8d6f804a522db01dc5c40d5c1f59198065d07",
-    "dist/2023-04-21/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "f8b54967642fbb715160497e7ea7dd5ecdb0d4f8583011ddb590e39ea96ef0df",
-    "dist/2023-04-21/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "f47b04ad9fc80f29100b56906754a17f1d6afa97942cdfb764269ea68e437592",
-    "dist/2023-04-21/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "5233106943cfc8f6665f800cf947415a429154ac8a3f5833cacb83b052cc9888",
-    "dist/2023-04-21/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "bc3a67a351897778a97eaa513b4dea9644ddee0bf76925c95fd9bbc3f3da368b",
-    "dist/2023-04-21/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "b8ddbb26d9422d65bdd5e81dae4b2fda27c3f47b12d6bf87e37bc2a5fd3d35e0",
-    "dist/2023-04-21/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "ded34445ffe8efb8255b61bca618a8a09db5ed95e54e02267796e41b221914bc",
-    "dist/2023-04-21/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "7c37ca08a4cf3495d0850acaaa69c79064501fe5e626c909cdb0cb936bc5f84f",
-    "dist/2023-04-21/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "fe2cbdf088b2738bacf75ccaaf9761b85f633c8fe56823bd05fd0e53570a58e9",
-    "dist/2023-04-21/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "cc1a68fb4322cd1336349abb5d1528dcf5c8e0113895f5fa6467d8f9c040c58f",
-    "dist/2023-04-21/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "e21f7c6f3bf939e066b8c2bae6eb8a26cfe124422e895b54d051e3013d8a1b89",
-    "dist/2023-04-21/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "638cd63bbec1312df98ce8e5b375b0ff1cf3256b8ef085e169639706f75f7f72",
-    "dist/2023-04-21/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "b615bcb14ba429fbb38cbe09f62bdad058dfb783055f067ceee58dd0799252aa",
-    "dist/2023-04-21/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "1797efad43a1a4bd63885e8b3a3e713ab7f971d8146f80a9b5ee72314e2c7fee",
-    "dist/2023-04-21/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "873cc18bb54a7db47763b88b91715360febf419302fd29fca2294073b09ae29f",
-    "dist/2023-04-21/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "3087b49def00930fcc4abea6391d4ded3e6fac8e66ac5275d58a3717bcbccc29",
-    "dist/2023-04-21/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "4a71c0720700ac94e1e7ec40ed0eb27cba60bab6f13b7b28bfdd15935c0bf639",
-    "dist/2023-04-21/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "eef5d412db6fd9535a109ad9575bb6d1428cf4bb56130d6c97332d5a56f9b504",
-    "dist/2023-04-21/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "453a0dcaf90ffb33af0e7994d317932e897980307897794d1143078c208dd42b",
-    "dist/2023-04-21/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "383a6196c67352f5fd6efad5dcd41cc325cef547baa2bf1376138cd628e1f16f",
-    "dist/2023-04-21/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "1c33e794c88b4740ddb5c7a1354f19471fe719b21402e67ca205cfbad6aa9f6f"
+    "dist/2023-05-30/cargo-beta-aarch64-apple-darwin.tar.gz": "ec0ef9ab4514f493675cf7c6c8539d29d4d9035813f3c2fe11df9f41cacb254f",
+    "dist/2023-05-30/cargo-beta-aarch64-apple-darwin.tar.xz": "1a9aa0848d79f7e8d13ed96e9df068a95c98056eaf569e1f5baa8ed02b1bd610",
+    "dist/2023-05-30/cargo-beta-aarch64-pc-windows-msvc.tar.gz": "4617ed30df22b2fc97b02d70bffd2f08e6bffacffee5f6f7bf73799372320802",
+    "dist/2023-05-30/cargo-beta-aarch64-pc-windows-msvc.tar.xz": "a7ea7ded3eceae4a3ffd21ab3b2af0e7e63e686e1d696508f05b764af5d071b0",
+    "dist/2023-05-30/cargo-beta-aarch64-unknown-linux-gnu.tar.gz": "05cd8f23b86bf8bf755d9300a344bcc6332398c81ec490a1afea8a3cfa489138",
+    "dist/2023-05-30/cargo-beta-aarch64-unknown-linux-gnu.tar.xz": "fc260df9c4fc721cf55edb2d10626b51232a566ccdf0fff76859542937aa8e3a",
+    "dist/2023-05-30/cargo-beta-aarch64-unknown-linux-musl.tar.gz": "be257b324db5f97e58d56c51c1da184689aeb53052731992454101abba5e69ba",
+    "dist/2023-05-30/cargo-beta-aarch64-unknown-linux-musl.tar.xz": "d12a3399e8a59121cd70620c735a2c3b33ca12d88db8b20f7f150f640ca2c3d6",
+    "dist/2023-05-30/cargo-beta-arm-unknown-linux-gnueabi.tar.gz": "f917a6722192bdac52994306033db82afa7aed3f7f0659bd3edfa125aad26286",
+    "dist/2023-05-30/cargo-beta-arm-unknown-linux-gnueabi.tar.xz": "d19e74b6dcca36100f667f752a3e61c0f4c0376f065d925dac1a04f35a2e2df7",
+    "dist/2023-05-30/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz": "4ee94ac076f491a725cfb0bd1fd562e76ba0c877f1ab3964289a93cf4d50e907",
+    "dist/2023-05-30/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz": "c054bece6c071b1c2633e59f7193e25ed3e29ab1b6cad5e62d9ec71304f92cc3",
+    "dist/2023-05-30/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz": "15ed708ecbf86769a5d3e64e2263f0c534db30f793ede9f4ea6e04fa6b462d5f",
+    "dist/2023-05-30/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz": "b11e35f7ccf65d9ee224d4695e0f769f52ed1e87f32221ab62a79d1e818dab88",
+    "dist/2023-05-30/cargo-beta-i686-pc-windows-gnu.tar.gz": "62509f8a6c096ea442ddfbc46c16942e905cfb5017b1cf85dc94f812da243bd2",
+    "dist/2023-05-30/cargo-beta-i686-pc-windows-gnu.tar.xz": "cfb63865159c01bfa1b4db6368219f255aacc9bbd94c2d04633cd705d53c6fbe",
+    "dist/2023-05-30/cargo-beta-i686-pc-windows-msvc.tar.gz": "81c5f9e12449ce7c7dca6a32ba18fa232df19085acf5650bfbed65e228c06b57",
+    "dist/2023-05-30/cargo-beta-i686-pc-windows-msvc.tar.xz": "acbac0d53c7ab771f3ae91c8461304ba811f8a067575c148e207311f425d694f",
+    "dist/2023-05-30/cargo-beta-i686-unknown-linux-gnu.tar.gz": "0bb73bb2d3abf4065cb559e022332c6ce9d6b2223c074b974fbc39450e46e345",
+    "dist/2023-05-30/cargo-beta-i686-unknown-linux-gnu.tar.xz": "11622821b4b11a02c9262daf4aa35aa2b71407362079557be604c72962175bf7",
+    "dist/2023-05-30/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz": "1f7c1a3d0879d6a04396cc31ca2e41dde5f9ca8cef360c9c44b32b909f4e8d4c",
+    "dist/2023-05-30/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz": "8952d2e179a80ee8257d89cfd417a6df50edc07c22c0d6e3ae55a7838cf51ba9",
+    "dist/2023-05-30/cargo-beta-mips-unknown-linux-gnu.tar.gz": "931a2f303b97bd21498e51370392e9ebc66d6cdbfaf537035245988781173b45",
+    "dist/2023-05-30/cargo-beta-mips-unknown-linux-gnu.tar.xz": "ce71db299106759857ba00ab57bc275bdb4817576a51333b8bfd6a9f1d7b8010",
+    "dist/2023-05-30/cargo-beta-mips64-unknown-linux-gnuabi64.tar.gz": "3f32c9a97da50ee98a2b60e8e3f5140941d12d3374a9926f169081d3b6ab6a51",
+    "dist/2023-05-30/cargo-beta-mips64-unknown-linux-gnuabi64.tar.xz": "568732ec25848560ed886d0742fcc5c84f6aef8dba16d530853aaddc3196553c",
+    "dist/2023-05-30/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "b9dafe965f6ee947b57b70ceb7317d9996ed35c11c761be45194e0415d41fd05",
+    "dist/2023-05-30/cargo-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "32226b19d7d6d46a99c7ca1b4d20e4228071ea9062bea564083633a2723c495e",
+    "dist/2023-05-30/cargo-beta-mipsel-unknown-linux-gnu.tar.gz": "69f8b8dccd7bce10f5c753b0e41f46ba6f29b32499a7b1e16ddcdfd9a592b5fa",
+    "dist/2023-05-30/cargo-beta-mipsel-unknown-linux-gnu.tar.xz": "95e7e39eef157e060dda4ed8613a78d1eba5065a1a8189d887a81a12ab432d27",
+    "dist/2023-05-30/cargo-beta-powerpc-unknown-linux-gnu.tar.gz": "613a81e9fec3814e4e5467dbcff0bb83e29b450733c4b36d8442fd2e8c5dc24a",
+    "dist/2023-05-30/cargo-beta-powerpc-unknown-linux-gnu.tar.xz": "2983b7fb28441408b53a49aeb3a7089c555460c31bb91b0a11d17f448c677de8",
+    "dist/2023-05-30/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz": "e63195ba700e4ab778e772ca935c4d3e42ce18474f3180226d254b0874cb65f9",
+    "dist/2023-05-30/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz": "eaaba4a4c35cdf30ba6225f652415312cf8d8a1d7edd2e4216f2379099b6d8c8",
+    "dist/2023-05-30/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz": "22c14003af58c489f07e52419edd2cfd50d8e2ed147a25f648855629d9f56478",
+    "dist/2023-05-30/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz": "2e513a599b7779dc37367e8ee28943b1568c296ba2b2e697f22b6cfabbb062c8",
+    "dist/2023-05-30/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz": "eb75f2008324c4956cc14989692904c20f412a30311a82f2a085516706f9e2a3",
+    "dist/2023-05-30/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz": "5cfe6a533005c70aaf14f86cdba51245272b0cb2c04a74a03da69744b18d40b8",
+    "dist/2023-05-30/cargo-beta-s390x-unknown-linux-gnu.tar.gz": "b37acb2fca2ec79e72f9ed5b87eba157a629ca1e3fa044d0caf6fd665451d09b",
+    "dist/2023-05-30/cargo-beta-s390x-unknown-linux-gnu.tar.xz": "cd590ac88ea46e6f347c1d433a3ffd661c4766504eae7197d06de69f3303ff07",
+    "dist/2023-05-30/cargo-beta-x86_64-apple-darwin.tar.gz": "a8db5d95e0d8ab4cfe323165abd423d17e1545d1b99bb2e8bf4b197ca2471e84",
+    "dist/2023-05-30/cargo-beta-x86_64-apple-darwin.tar.xz": "95ceb8066879807752f9f7a70aeb2e9d08991659f49d64249b04c2b1ea545ac6",
+    "dist/2023-05-30/cargo-beta-x86_64-pc-windows-gnu.tar.gz": "2971558e43ee1e6a8c6ce5277b902a537d7f6d31ce714702e89efc468cf8dfde",
+    "dist/2023-05-30/cargo-beta-x86_64-pc-windows-gnu.tar.xz": "6ad42cca05e6c752424c3725516e24e9b1051e201b3ef0c2e1d8ec2e44973717",
+    "dist/2023-05-30/cargo-beta-x86_64-pc-windows-msvc.tar.gz": "c5f0cf8ebd206dfc39c0c889ae8670a6b6b2fb55cdbfeee3ba8b2ec72daf6135",
+    "dist/2023-05-30/cargo-beta-x86_64-pc-windows-msvc.tar.xz": "90d13c515e737193858f48901d8f150c5528a09e2a1c8a08987140f2ad8fbc03",
+    "dist/2023-05-30/cargo-beta-x86_64-unknown-freebsd.tar.gz": "a183226ff05ac8d16baf03c81a9281f42e1de5a0b270b1592ba785397e4d32da",
+    "dist/2023-05-30/cargo-beta-x86_64-unknown-freebsd.tar.xz": "96984a716ac37b2888181b00939c975a544cdf21a0dc1db5bcd5b4468e28eeab",
+    "dist/2023-05-30/cargo-beta-x86_64-unknown-illumos.tar.gz": "997cc3167983b80bbd8d323a61d718022ff0fd9827299379166e7240b0fbb2ff",
+    "dist/2023-05-30/cargo-beta-x86_64-unknown-illumos.tar.xz": "6f1c276cfc53f17cae1e1fdf372275a39c60a3d4c543dbed553222557707c6e9",
+    "dist/2023-05-30/cargo-beta-x86_64-unknown-linux-gnu.tar.gz": "a5075bdb4ca1b4a5b5cc734a131277967a5a34c9915afa52e3275da60e87993b",
+    "dist/2023-05-30/cargo-beta-x86_64-unknown-linux-gnu.tar.xz": "417b88bae9f028c94ee0563baf421abf8a18ceffe35d731ad9736f71d6a1b34b",
+    "dist/2023-05-30/cargo-beta-x86_64-unknown-linux-musl.tar.gz": "495b66a5e9dd3987c02f004eb8e3515b84dc132b274e726df36359cc9974f4a9",
+    "dist/2023-05-30/cargo-beta-x86_64-unknown-linux-musl.tar.xz": "faeb090c8e1d15b20c256eb7b326de2375812ffc7984e8c11e28a0add3fddec5",
+    "dist/2023-05-30/cargo-beta-x86_64-unknown-netbsd.tar.gz": "adc9720e065861ff8aeeec8ffdc231161755e603301521982f6ef405d2d12c95",
+    "dist/2023-05-30/cargo-beta-x86_64-unknown-netbsd.tar.xz": "2def53546856b6cce7ddfce00329fe05be0f649f0b8421168fbab85d9c23715d",
+    "dist/2023-05-30/rust-std-beta-aarch64-apple-darwin.tar.gz": "ebd92098d173efea06a3e2d2edec299483fc77925427417e182800567ff6d642",
+    "dist/2023-05-30/rust-std-beta-aarch64-apple-darwin.tar.xz": "028c6269d40f8adf897b5e6b61387ce49cb1c2c82244965d48efa68ca71d74e1",
+    "dist/2023-05-30/rust-std-beta-aarch64-apple-ios-sim.tar.gz": "ea5654c6a23488e56c0b1c8c8c655c449bcadc9c3676db9ff37ef3fe742c4f9e",
+    "dist/2023-05-30/rust-std-beta-aarch64-apple-ios-sim.tar.xz": "9b0542cd5aa8ab4df51e41800e99563a8a3d6a202d32008a9166ba29d40c7ce5",
+    "dist/2023-05-30/rust-std-beta-aarch64-apple-ios.tar.gz": "ff1bd99fa25176ccb5fe5ef9dca6bf902094c6b6f2ba1985481c1a0fb58cbc7d",
+    "dist/2023-05-30/rust-std-beta-aarch64-apple-ios.tar.xz": "3009eb898a50aebf7fda060b5abf1098271061431f732542e2d1e2bd98e17f60",
+    "dist/2023-05-30/rust-std-beta-aarch64-linux-android.tar.gz": "15ee7baf5a04c9651abc176b3d6679104a395c128724256aadaaf1174d76dbab",
+    "dist/2023-05-30/rust-std-beta-aarch64-linux-android.tar.xz": "93ffc5e6252ba061966338ebae85c1addea410cb1c6cc34936c86376a4ae264b",
+    "dist/2023-05-30/rust-std-beta-aarch64-pc-windows-msvc.tar.gz": "c13e9ef9c5c2088f7b7d111861bc1c6e11b2e2e26e5e43f44fcdb1629f1a5183",
+    "dist/2023-05-30/rust-std-beta-aarch64-pc-windows-msvc.tar.xz": "e19e125a06f6c1cfe719cc2c1e1925609c315c368e95fd32d75ace3f1dfdad32",
+    "dist/2023-05-30/rust-std-beta-aarch64-unknown-fuchsia.tar.gz": "2d8e20471633b28d5fac2f443ddfce59f84c49e87065f6538924c4484054aa85",
+    "dist/2023-05-30/rust-std-beta-aarch64-unknown-fuchsia.tar.xz": "bec968d53659373451860525922b6833204e0e61efa192739d59fe64fc8fd8e1",
+    "dist/2023-05-30/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz": "4092203bfab27e32bd3fe2254cb91cd70d332a613a1d2286fbe985036c6f96ea",
+    "dist/2023-05-30/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz": "a288efac80a2692858669537daa6b2657470dc4124541654a22d9ff415ad0389",
+    "dist/2023-05-30/rust-std-beta-aarch64-unknown-linux-musl.tar.gz": "d4e1d2ccec8e8ff63f77ea678864d2ec569da5c8a7ae625b820827fd5b4bc193",
+    "dist/2023-05-30/rust-std-beta-aarch64-unknown-linux-musl.tar.xz": "a14a29b6d213a1e744d7e9273c674cc97de9266764ecdb62ec1b9ab7dc2c81be",
+    "dist/2023-05-30/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz": "cc8facb1c53ee1cf734933fb997c3eee57a6a0ac2fec8af571e01ad01c09e023",
+    "dist/2023-05-30/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz": "d84cac6b97e396bcb64f2c794f0b2ebe73217a07a46e2a85a8b6ce73ebf279ce",
+    "dist/2023-05-30/rust-std-beta-aarch64-unknown-none.tar.gz": "e119575ce29c103ca82134e216ae3a77b01252ca7348212bab36ccb5d785e6b0",
+    "dist/2023-05-30/rust-std-beta-aarch64-unknown-none.tar.xz": "21472aa2b47a16e479f8759bbd206090169586fb29ab0f976b47fc7bc62c81b8",
+    "dist/2023-05-30/rust-std-beta-aarch64-unknown-uefi.tar.gz": "699727b60d15a4386659c8679aa612455b4a57fbd0901172d7daa7fc5ca253a7",
+    "dist/2023-05-30/rust-std-beta-aarch64-unknown-uefi.tar.xz": "95949ba372aa947c1bac030805af76644a99d6098442054bada9278b5c8f0722",
+    "dist/2023-05-30/rust-std-beta-arm-linux-androideabi.tar.gz": "765a7f836bff1ed7b10816a0ace2cdeb0b9aa383fbaa90fd0fba203093b4255c",
+    "dist/2023-05-30/rust-std-beta-arm-linux-androideabi.tar.xz": "66b909b5a4e6a19f4b45ca5396353437da76a350c994696d25e5b617b54e7df6",
+    "dist/2023-05-30/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz": "43f2e2230c405809115bac27ff1b344ec7da7e410728c88092e021688819aa61",
+    "dist/2023-05-30/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz": "8eb6821edf96ad1ead828a95513e8ed8deafe1f1697cc965e6e9830175ce41a3",
+    "dist/2023-05-30/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz": "7fcc7ccc6d705636bbd37096707358eaeb192179409983a6c3681a2664446ef9",
+    "dist/2023-05-30/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz": "506f392a315b45d458111b30bc3d13b266a43ed1890418e8c85e02e9eb0cd284",
+    "dist/2023-05-30/rust-std-beta-arm-unknown-linux-musleabi.tar.gz": "6b42b38873821320ec597ec44767ec03d87068389a61360aa566347506ad2a8e",
+    "dist/2023-05-30/rust-std-beta-arm-unknown-linux-musleabi.tar.xz": "33324c183092e505b77a76a0ea6d0e169838dd76e96a8ad94b142843449ec9e3",
+    "dist/2023-05-30/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz": "414e4834f232862cc6b371716f014a7384e23fa4d4997b25ca77ba03ce4acda3",
+    "dist/2023-05-30/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz": "bf60815516d3dd2d4452de0985dd95a615b905789669dcfe225eb2fa6b26c3d8",
+    "dist/2023-05-30/rust-std-beta-armebv7r-none-eabi.tar.gz": "132fa87ff6c7d9a94871edbc2a9634f96bf16ea46b04978680ea25855530b9ab",
+    "dist/2023-05-30/rust-std-beta-armebv7r-none-eabi.tar.xz": "1c2d6404ac467cff3ffb2f440a807b35532d03469730131b53b4ddd9e7f43f57",
+    "dist/2023-05-30/rust-std-beta-armebv7r-none-eabihf.tar.gz": "92c3b59c2cd7324d27edb928292017f27a9e88d12a5e5cc66a851be35481a29a",
+    "dist/2023-05-30/rust-std-beta-armebv7r-none-eabihf.tar.xz": "b545ba9763df61d95faa14e59124fab46d09ae95707e9686f325459140abb950",
+    "dist/2023-05-30/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz": "2accb0f63c0ffb0aa0db99c05e5eedee369348d2a571df1b87689225cdb61d44",
+    "dist/2023-05-30/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz": "fae4c7f7549789f51c1ee7037fa6142ec8ace96d8438ed964bf15f9241948fab",
+    "dist/2023-05-30/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz": "414978972ee622cfaf64dfd4fbe3cb5ec5e2d8436f129a75283d98fadf17f595",
+    "dist/2023-05-30/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz": "abc1719b2b29ad091a11d9515e633dadb98a665fb209a47e291a490d4e79f6c9",
+    "dist/2023-05-30/rust-std-beta-armv7-linux-androideabi.tar.gz": "c1159cab2a4bbb24e2ab7135d449583dd0e2f1fb329b7420aea69b005c9556a9",
+    "dist/2023-05-30/rust-std-beta-armv7-linux-androideabi.tar.xz": "b37e60b73d802535e2832351a344c3180bfe931cd14a03df5ea8bee8bd2f3f3e",
+    "dist/2023-05-30/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz": "65b9809fcda771576c1586c239d5dfaf960c2968e4ba09473f4d304b2684eeb1",
+    "dist/2023-05-30/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz": "331788bfc44fdeb49d85ef84591c400b95f7939661a722aaf36728617b86ce6d",
+    "dist/2023-05-30/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz": "b932fd571a95f97e9a5dac39c99cfe488f2d29f9e86e9e2821b16df33cabc6a3",
+    "dist/2023-05-30/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz": "7427c8103ecb0d0cf3f211f8700f0cf2bf6969e982ff599c20de87027224a814",
+    "dist/2023-05-30/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz": "1206cf83b0bdf96bb1fb2c074c4078f99242d6eb273321e8090ed2cedb760c14",
+    "dist/2023-05-30/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz": "5f1ac81a4508e6f2fb9b931cb556cb2d45ebe88e90eeeb7c25690a0f9448a0e1",
+    "dist/2023-05-30/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz": "a833ab5f38416ee1d94565db936dd0f351ff4313456f6faecf581e07508080e5",
+    "dist/2023-05-30/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz": "ba7c2dc66a19a960bf4e914cc30f8c40cde435d4da11e4dc44208cb950c67892",
+    "dist/2023-05-30/rust-std-beta-armv7a-none-eabi.tar.gz": "34ca46fc29871e03490d17df73e55f250699204cfb1ea0d72427434212c4f7e6",
+    "dist/2023-05-30/rust-std-beta-armv7a-none-eabi.tar.xz": "d6b58d542f3219e5075794588c2183a7849530b6ea174dd8cdcf1cc289c4c13e",
+    "dist/2023-05-30/rust-std-beta-armv7r-none-eabi.tar.gz": "ff262f5ac8cb94feaccfac8715f6a97a1edbf59e8778add720ec356203e2f9b7",
+    "dist/2023-05-30/rust-std-beta-armv7r-none-eabi.tar.xz": "ae386368da77e529eeb40c1d123bca34b07d65cc359d790949f257a541abdf91",
+    "dist/2023-05-30/rust-std-beta-armv7r-none-eabihf.tar.gz": "26e123410afb4c0aa7c110c12d31ad00b99f6ffc042745de2bca34b86e04c685",
+    "dist/2023-05-30/rust-std-beta-armv7r-none-eabihf.tar.xz": "ce3400eba477600cc4675b7d91366ca80e82ce656b62f83cea532b60248ad7d8",
+    "dist/2023-05-30/rust-std-beta-asmjs-unknown-emscripten.tar.gz": "6874686cdc7e9d1842cf59c1d55570379cd0f3933da55683435b7b36178ca106",
+    "dist/2023-05-30/rust-std-beta-asmjs-unknown-emscripten.tar.xz": "1a8cf6d6d86101c84e456667d9bb9866039b81e833e6b7bdbc227e6af540fccf",
+    "dist/2023-05-30/rust-std-beta-i586-pc-windows-msvc.tar.gz": "7f121cf6edf07b54e731e863d5c3ec92da88e39e88057e96b07f31a1cc16cb8b",
+    "dist/2023-05-30/rust-std-beta-i586-pc-windows-msvc.tar.xz": "a3c8dd03a35b272045fffd57d773064556637241ecd83218c78d9f20c5200b12",
+    "dist/2023-05-30/rust-std-beta-i586-unknown-linux-gnu.tar.gz": "5a3475ae3f6974ff33e7372867e1cfd6c944dab4af52e4daabdd471d270effd0",
+    "dist/2023-05-30/rust-std-beta-i586-unknown-linux-gnu.tar.xz": "4f2c386aa8f2689f88069ac96a88eb72bd56c6f3d3f002e7dd095fba3d0cd8ca",
+    "dist/2023-05-30/rust-std-beta-i586-unknown-linux-musl.tar.gz": "2659f824119c5abff708e1e282915a291989a98eb7710676a24adfe52c851f93",
+    "dist/2023-05-30/rust-std-beta-i586-unknown-linux-musl.tar.xz": "07960cf2f28f52eaf8351573da0e3964481f0cfa5502ab5b5e3ea4ad535dcd6e",
+    "dist/2023-05-30/rust-std-beta-i686-linux-android.tar.gz": "ef4eea9c214eea6a4d1425fcee382f0553a66d6d17ce33c3949d7df24e76d1d8",
+    "dist/2023-05-30/rust-std-beta-i686-linux-android.tar.xz": "3e54d56aab895defcab4c31d7fa0ed731387fae0a5df4ed56511173a20f4ab9b",
+    "dist/2023-05-30/rust-std-beta-i686-pc-windows-gnu.tar.gz": "92b09c74bc552e01f68d0090316287026340c92bd8804cffd5d2bbbe44124822",
+    "dist/2023-05-30/rust-std-beta-i686-pc-windows-gnu.tar.xz": "2f96ceb5fed911b830553e354bcc47cc6f1983e22a4b1227e61983308e184457",
+    "dist/2023-05-30/rust-std-beta-i686-pc-windows-msvc.tar.gz": "2251b6cdd4d9d7cd2990efa1641e93ca8fb51e7228eb95305a468e61c4a53d3e",
+    "dist/2023-05-30/rust-std-beta-i686-pc-windows-msvc.tar.xz": "e4c00779bea04c7e5a2f859900325355d64e9ef6cfbc452a3a8e5fd20b440518",
+    "dist/2023-05-30/rust-std-beta-i686-unknown-freebsd.tar.gz": "b731321a1a2beddb2d64009e77b883d97e679bcca8ae454e9e5b33a72461c220",
+    "dist/2023-05-30/rust-std-beta-i686-unknown-freebsd.tar.xz": "2d99b9633fb37ad1f017539f65dbea5644b6d85a44e657a48f71766b306cc172",
+    "dist/2023-05-30/rust-std-beta-i686-unknown-linux-gnu.tar.gz": "1782c79086dff3dc53d15894a6c3bec8dd87f457fab73c472c302eded6258d10",
+    "dist/2023-05-30/rust-std-beta-i686-unknown-linux-gnu.tar.xz": "8eb6afcc2fe17a383212f24e09db66ce37e0662925039f87a47bb50f44d4b671",
+    "dist/2023-05-30/rust-std-beta-i686-unknown-linux-musl.tar.gz": "4890d5adbee68aaac44e23b84487a4db6a602438d14b046bca23193273130485",
+    "dist/2023-05-30/rust-std-beta-i686-unknown-linux-musl.tar.xz": "9b00cdfc7890ca8a169556b2af8b690f59a17b49f44669a64fb0a27e42ba45a2",
+    "dist/2023-05-30/rust-std-beta-i686-unknown-uefi.tar.gz": "f672aa10394ec1f4998a29fd4e871d5da4057de5a67ef1e88e99fbf044485572",
+    "dist/2023-05-30/rust-std-beta-i686-unknown-uefi.tar.xz": "5da375bff19cbd2b6c550514b5452005cb1cb19c29f41e3efbe1652b367ee9ee",
+    "dist/2023-05-30/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz": "e52febf6ff0bead6c72efdf5afbda8951a8a52ec87980fe42179d624b21b51fc",
+    "dist/2023-05-30/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz": "a1b218f627223d60c231441752ae1696612471e90a3367a471ffe367309ec4e3",
+    "dist/2023-05-30/rust-std-beta-mips-unknown-linux-gnu.tar.gz": "1cade6c46209e8cf605794d18c6c8a2d0cdfd81b154802f0e916f5b59688f77e",
+    "dist/2023-05-30/rust-std-beta-mips-unknown-linux-gnu.tar.xz": "98cbb0c41f140acea077cae5145a28153f0d5f06e6009cad73064365d3bc373b",
+    "dist/2023-05-30/rust-std-beta-mips-unknown-linux-musl.tar.gz": "cfaedf4168ab803720bccf508ff04fef073d5b73ab6d9a27aaa5473edfe85b2a",
+    "dist/2023-05-30/rust-std-beta-mips-unknown-linux-musl.tar.xz": "7a9b2ab5dd58f61c1656081d0606ab60fade1e3f7c2d91d40b6dbb8255359df1",
+    "dist/2023-05-30/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.gz": "670990fab0d668344d8b0b67a7613415c1fe596f73b2bc800e2f8acefed5a447",
+    "dist/2023-05-30/rust-std-beta-mips64-unknown-linux-gnuabi64.tar.xz": "3fd409a760598d6b830f4469c474a2d50e0332886f5e90bd6d80960cb593f948",
+    "dist/2023-05-30/rust-std-beta-mips64-unknown-linux-muslabi64.tar.gz": "2d583489021ea04e11a1c19743c29f77622cb95102122d16cbc77d24d6e6de8c",
+    "dist/2023-05-30/rust-std-beta-mips64-unknown-linux-muslabi64.tar.xz": "4a340a6d2292256b2f370931b74490afc07570c58f95a5a97be6840c6a426e3e",
+    "dist/2023-05-30/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "7a19789581b82f31c90a83d604a2894e82ce309b26598b0acb028f8ba749aa39",
+    "dist/2023-05-30/rust-std-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "2507a916346c53dd44dc590334630eacd5b4c5a57a240a936203a73b4e96d507",
+    "dist/2023-05-30/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.gz": "4b676b406389acc80c61fe89dbf4f8439436c8ef5f2e4a7f36202a9a48ddd487",
+    "dist/2023-05-30/rust-std-beta-mips64el-unknown-linux-muslabi64.tar.xz": "83ad872a06bd1cace948d542e1a69210f550abe536d74b0dbf036cc02d7c05a1",
+    "dist/2023-05-30/rust-std-beta-mipsel-unknown-linux-gnu.tar.gz": "31bc6097eec7ac51e5e923199aec47fb129f34dc472b3ba3d2398c4481aaf12b",
+    "dist/2023-05-30/rust-std-beta-mipsel-unknown-linux-gnu.tar.xz": "68bffca2afe433a435e8712174efbd61b628e5dacdbf151713f7b43c67804e57",
+    "dist/2023-05-30/rust-std-beta-mipsel-unknown-linux-musl.tar.gz": "34520ba878f3ab24d86f965d7470292df65deed971d1a3f1b078c3e4b353ead3",
+    "dist/2023-05-30/rust-std-beta-mipsel-unknown-linux-musl.tar.xz": "8ef5dffe7ed584ea59a8d1114f15d1eeb2bd598239fb3d2bc3efbbbe3da36c44",
+    "dist/2023-05-30/rust-std-beta-nvptx64-nvidia-cuda.tar.gz": "2297e2cb62b5d1085318d19334f55277e547b0d7bed86a29f60859f5e029d259",
+    "dist/2023-05-30/rust-std-beta-nvptx64-nvidia-cuda.tar.xz": "3f012c0cc6c7adad8e08f40c697c0248938103e5a1949c07d1139ef3d5a8cf9d",
+    "dist/2023-05-30/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz": "8438185ba380e24cdae232aad740e9cc580e2bc4eb4b4aacc006a66e3b846ea0",
+    "dist/2023-05-30/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz": "c751381d33ada7720f3aa10a242a26055806e56cfbc2348c2f21fb2b767f46df",
+    "dist/2023-05-30/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz": "1923978ae0a1130fea64fa35ef3aa9c5808b8d8a4af89cd78e0a3edf448404b9",
+    "dist/2023-05-30/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz": "36481e7b876977c357c1171d2bf4641f55ca7df70288c5aae0e94bd37380928d",
+    "dist/2023-05-30/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz": "965b9ee397d3ae5fe783c89e9b587dfbef1d3a572ad1503dfa997cb0016444ec",
+    "dist/2023-05-30/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz": "5963b85d5e8e41d86fd6447ad99ba0a3b36d07657c935fbd810c259d1bb6ccc1",
+    "dist/2023-05-30/rust-std-beta-riscv32i-unknown-none-elf.tar.gz": "c38b5bce61132789809aaed43151739ccde285186d42882f411610170ab3bded",
+    "dist/2023-05-30/rust-std-beta-riscv32i-unknown-none-elf.tar.xz": "973389204e68468825084d29934c6d89ef3215563402cad62d0630764e0f7adf",
+    "dist/2023-05-30/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz": "39153c0171d86611ebfe77f0cd2d26ae9a432910778b86163fcd29ef633ce8a3",
+    "dist/2023-05-30/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz": "1f90107007322dd3167c0a11bf50ab3c939f52fee06ac8cf737891cef7be030e",
+    "dist/2023-05-30/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz": "ea75cc8c20192334d3f22719fcd67343d64c04a64cb1750f2182548b34643368",
+    "dist/2023-05-30/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz": "2c48229fa6c41d68535590f8993c0dc45325d890fadad0c6ebcc7a0afa1c77a4",
+    "dist/2023-05-30/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz": "041dd4a64a699968a487c22893c11ef0944b6e920cdd23f2c904e3cfd847700b",
+    "dist/2023-05-30/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz": "6a5558581221b88a4e99ba3231bb0c35445537b1e0f1f0b6e02345297df9f1ee",
+    "dist/2023-05-30/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz": "08830dfee466dd7e295489c2ab2b954e4d88001f851a5c96ed19de158c594490",
+    "dist/2023-05-30/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz": "2a0bd37a0250ecaebe522df54201dd0b70fadcac9df01dfd70f681fa27385627",
+    "dist/2023-05-30/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz": "b7c82cdf881d8d5052e365cbeb1966bc4c59627692619642617d4cf9fc8dd02d",
+    "dist/2023-05-30/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz": "da29b033566bb1f97a98851fba1b41818d4a3a41d65713e4f1644e0ff43e0ef0",
+    "dist/2023-05-30/rust-std-beta-s390x-unknown-linux-gnu.tar.gz": "731fdf689c118040eb79917fe194a7691f82b5c68246d99496f21fc8d095c6f2",
+    "dist/2023-05-30/rust-std-beta-s390x-unknown-linux-gnu.tar.xz": "a7dfdbc15fcf1311b813b0ca8fe07270b28d1b0e7a87bb64663aa3999367430b",
+    "dist/2023-05-30/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz": "445d91c3240b79d86d48e47f3553a14375932c9751fe4c917357e34890b86830",
+    "dist/2023-05-30/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz": "6fbcf8e4e09a93216053781c20d2879660cac129d078ed610cb1e6db72d9d59c",
+    "dist/2023-05-30/rust-std-beta-sparcv9-sun-solaris.tar.gz": "e45cece10a961fc046adf7721f920e592bc7c0c5c276bb55bfc6b6c8fb95486e",
+    "dist/2023-05-30/rust-std-beta-sparcv9-sun-solaris.tar.xz": "b3778ff0a994f38133e49a448c091e51fbfe90a3fcf4ddcf209a3b49bd9c1c8f",
+    "dist/2023-05-30/rust-std-beta-thumbv6m-none-eabi.tar.gz": "5625a51ff41dd444d32d653c329139c906edf26e20782765feaf0168b4fce643",
+    "dist/2023-05-30/rust-std-beta-thumbv6m-none-eabi.tar.xz": "4a2ca2f8f99f297fa2b17c423b8c850476fb80a2bd19e6fd914f2efa813e13c1",
+    "dist/2023-05-30/rust-std-beta-thumbv7em-none-eabi.tar.gz": "26189595572717cf9721394f4f604a7c81cc9066813bda81e0eb8508075d4510",
+    "dist/2023-05-30/rust-std-beta-thumbv7em-none-eabi.tar.xz": "f4f88f6a85761207a3c1496ce3cbd87608de99febc74e01ac0851577c33ec248",
+    "dist/2023-05-30/rust-std-beta-thumbv7em-none-eabihf.tar.gz": "246b7f137c982e32d3f80e34c8e26a4ff64072b8f01d012fede280a1c356ec0b",
+    "dist/2023-05-30/rust-std-beta-thumbv7em-none-eabihf.tar.xz": "14904ce77090bacee8727529a2cbefc14ec2ba21a94e90e15b04841e562c7100",
+    "dist/2023-05-30/rust-std-beta-thumbv7m-none-eabi.tar.gz": "d02b075118d4aa29e7a842c95b7f5fb7f438f8d11c8c6ef3059a812993862811",
+    "dist/2023-05-30/rust-std-beta-thumbv7m-none-eabi.tar.xz": "564352083d92236466aaa6742b0df362f6dca5ea30696ab0b7c68da7b2c1ea05",
+    "dist/2023-05-30/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz": "6f339f2a9491ac5cfee317fbb6539a14b0f1d6cf6cc8ccf1091f3493bd5d3e06",
+    "dist/2023-05-30/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz": "475593fcb658f7e01610c2aa9cbf76f3db7b1306c6697ea40626ae51dfab3b28",
+    "dist/2023-05-30/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz": "fdb20a3f739747105e72718b2a2e79a23b2dc603153ad8feca51a4f6791edb22",
+    "dist/2023-05-30/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz": "ed9fae43e824c70ecf1efde92a45a3c85781b2913597ed0d60e75c7410145968",
+    "dist/2023-05-30/rust-std-beta-thumbv8m.base-none-eabi.tar.gz": "68f91796bdc580170716ec00be393c939359657b6f5aeba7c3e88ca0d068f8b9",
+    "dist/2023-05-30/rust-std-beta-thumbv8m.base-none-eabi.tar.xz": "2c014f52137862b2e7355812aee142ace2b4770c25dadac8f8e99239d82d7ca3",
+    "dist/2023-05-30/rust-std-beta-thumbv8m.main-none-eabi.tar.gz": "d2b691c5a6b11b5489898673e3d69aaaeccd2b97b0856421b1aa5c91fd48c5af",
+    "dist/2023-05-30/rust-std-beta-thumbv8m.main-none-eabi.tar.xz": "ff61566f1d84d80c0263d58cb4016201e2694278bcd9233ca2cafd19c47fc61c",
+    "dist/2023-05-30/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz": "04c29db24b00c9e377f22266ad0bdb3126febfb39a35f83143ec7e2e052cf7c2",
+    "dist/2023-05-30/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz": "651a8fb666a1412bffe84d39e92e01ba3fea6687d92f90ba0e3a4bdfbcea8dc0",
+    "dist/2023-05-30/rust-std-beta-wasm32-unknown-emscripten.tar.gz": "f4ea3e81bbaa7e6569c18e0f111aeca8a5cbf565403f7c0fa9c2da0858ee9548",
+    "dist/2023-05-30/rust-std-beta-wasm32-unknown-emscripten.tar.xz": "14ac309023a66949fbd3110eb7f53035abb54f79711e848f382e2953a702eb5b",
+    "dist/2023-05-30/rust-std-beta-wasm32-unknown-unknown.tar.gz": "4bc81b56c91e6771154d30cdae66c8f09d5c1e47ead91e59a1d98c9c7f2eefa8",
+    "dist/2023-05-30/rust-std-beta-wasm32-unknown-unknown.tar.xz": "b32619fbbdd47c901c41f385b3a6c1766f5439d8f6fef36409e1a8ba4ad5d847",
+    "dist/2023-05-30/rust-std-beta-wasm32-wasi.tar.gz": "c505c26f333208c5b38229b4fcf60621748303ff23193254e321386348328afb",
+    "dist/2023-05-30/rust-std-beta-wasm32-wasi.tar.xz": "f2b675fc1f95c5c3cfc78e10ad9b1322d920d429ae98b47580b7a1a7536dbba1",
+    "dist/2023-05-30/rust-std-beta-x86_64-apple-darwin.tar.gz": "e58d900bf9a1fde7867470c2c87b41c8ba8cdcef6b9653899c53d21f7b16d43a",
+    "dist/2023-05-30/rust-std-beta-x86_64-apple-darwin.tar.xz": "4cf95d2f670c00906e89ed8539bc90a45f0398bae84916409a26ceedfbd5b9ad",
+    "dist/2023-05-30/rust-std-beta-x86_64-apple-ios.tar.gz": "a5f8ab9c9d2d4a71aacf2221e06494bbc0ff9076d3c7dadbd0d4473f6e900c79",
+    "dist/2023-05-30/rust-std-beta-x86_64-apple-ios.tar.xz": "b3d6b2795c0d50aa8f1665579f1e3a1e056071cd50f4a464863608739c8fa62b",
+    "dist/2023-05-30/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz": "08157017fa1d7a64078a7b2a3e7662b0f76174de3bbd1ca80bed40ec5dcb7407",
+    "dist/2023-05-30/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz": "0588ec9de11c46a0cb705690e2182fe5acfd0d33e71f29dde9798f9025c137e0",
+    "dist/2023-05-30/rust-std-beta-x86_64-linux-android.tar.gz": "9aa164600f3adfdcf369b23e69f9f5c81757f21b9fef1419bc06d2b9474e4120",
+    "dist/2023-05-30/rust-std-beta-x86_64-linux-android.tar.xz": "635c8d4edf68790079eacac7d5754fe7ab431787dd01ebec7184c03e65e78c4a",
+    "dist/2023-05-30/rust-std-beta-x86_64-pc-solaris.tar.gz": "622e359c4178cf626fe63f95164915ec4289c5898851a9282da9780b847e8414",
+    "dist/2023-05-30/rust-std-beta-x86_64-pc-solaris.tar.xz": "ab2b95f4104691d44d455f4e5391b187b712b632cd0ec11baf1d29291814d770",
+    "dist/2023-05-30/rust-std-beta-x86_64-pc-windows-gnu.tar.gz": "08f28724ee08b13705911c5c9be7773f8ac935329fa37548b8d46118fc5e244b",
+    "dist/2023-05-30/rust-std-beta-x86_64-pc-windows-gnu.tar.xz": "fa3fcd87e50aae6f1893b65b027ae6f705f7c42cba63cebfca1e49dd3c2af966",
+    "dist/2023-05-30/rust-std-beta-x86_64-pc-windows-msvc.tar.gz": "c208ad4e8ea70e45b6d76b7a88491a33f30f1415043a26ad96908faefdb37eb7",
+    "dist/2023-05-30/rust-std-beta-x86_64-pc-windows-msvc.tar.xz": "afa64e5bccb5138d86349f8564f82dcdcf009e7bd07121d193ead9864f2ca1f5",
+    "dist/2023-05-30/rust-std-beta-x86_64-sun-solaris.tar.gz": "e2d8fa74156623a3cdc944b1e0eb5683b661dbbecd779b5621777413d4918fb4",
+    "dist/2023-05-30/rust-std-beta-x86_64-sun-solaris.tar.xz": "2a75d1d8918febceaaaf8ea4c89827798099ab69063878a71afaef5ae17691bf",
+    "dist/2023-05-30/rust-std-beta-x86_64-unknown-freebsd.tar.gz": "24cf8f9bad86110308215d52aa9ac3b0dffb8640508e718d14ee9928fc68f59c",
+    "dist/2023-05-30/rust-std-beta-x86_64-unknown-freebsd.tar.xz": "0babdccec106b4cd20574c9722b36e407a1d028856989ff5e390172876ab3e28",
+    "dist/2023-05-30/rust-std-beta-x86_64-unknown-fuchsia.tar.gz": "0a983d8fe5aa649452f93cf4566d59b091d79da1e325f2da6b0844ef842f7a7c",
+    "dist/2023-05-30/rust-std-beta-x86_64-unknown-fuchsia.tar.xz": "7bf8fa91b5ecce8744e29a47740f52a57c8faf1fa4e125736103890189cc23b9",
+    "dist/2023-05-30/rust-std-beta-x86_64-unknown-illumos.tar.gz": "f90b0c2fb060f84b53052852478b474d587f8c51ff1750df5922f2ea8b66fe2f",
+    "dist/2023-05-30/rust-std-beta-x86_64-unknown-illumos.tar.xz": "6075598069ed92e26615e49bdc6f8c571d7f194462588b941f5479b0ab137994",
+    "dist/2023-05-30/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz": "8c9a48ec0db55f07200bc73b292a5ee7a603b6b924eb4a1044609d854e820554",
+    "dist/2023-05-30/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz": "0bcda45a340128c3e69ec0d10b08ea11edd764870e5a8fcd741a42949a025325",
+    "dist/2023-05-30/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz": "0f8b6583c8dc192253c480aee8c743013758b7ddfacb08e957c57d1feabd5824",
+    "dist/2023-05-30/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz": "a8086bb72e9ce9b9013dac6ea159fc15147a4d1658b5e11d9910f1486828796e",
+    "dist/2023-05-30/rust-std-beta-x86_64-unknown-linux-musl.tar.gz": "f801f8382e5439a98115c0ce8a1ead8acc983f01a09bb4c6ec3add9324f16334",
+    "dist/2023-05-30/rust-std-beta-x86_64-unknown-linux-musl.tar.xz": "69cb7620f271d64db234166fc9db37f4b5d60b6f4b9da43d02d21baa31c5da67",
+    "dist/2023-05-30/rust-std-beta-x86_64-unknown-netbsd.tar.gz": "2cf6c1f646286ecf2fe0a0e8f7eb079e7402dddb556273bc2d12be61b5ee6341",
+    "dist/2023-05-30/rust-std-beta-x86_64-unknown-netbsd.tar.xz": "0a4845f220640f00b3e0a1d0957050e0c7258867f6f8d6e174277d3659214d46",
+    "dist/2023-05-30/rust-std-beta-x86_64-unknown-none.tar.gz": "9a1fb11c9a5264232ba1ad2d3c89d1dfb9c135d000b812135932521932ba1b86",
+    "dist/2023-05-30/rust-std-beta-x86_64-unknown-none.tar.xz": "5598a18d71f1c82e796c136ba4d09b38e24e201ca199752959f0eb094cc49c30",
+    "dist/2023-05-30/rust-std-beta-x86_64-unknown-redox.tar.gz": "6ec43ffac6b70a67e08308d4869334131025c9acb0e2036a072e9e594ec46acd",
+    "dist/2023-05-30/rust-std-beta-x86_64-unknown-redox.tar.xz": "eb801580d8ea50d2f7a9a9d78d9a3c10bd3596c84740b3c8b610a86157942b50",
+    "dist/2023-05-30/rust-std-beta-x86_64-unknown-uefi.tar.gz": "051700f1977665f3b8119af984ece787ed84838d0ae0443bfd475d91d76f1202",
+    "dist/2023-05-30/rust-std-beta-x86_64-unknown-uefi.tar.xz": "1db1d6eff963a7d1667d1f5542de5484105d39436c0c502044222d7f749299ea",
+    "dist/2023-05-30/rustc-beta-aarch64-apple-darwin.tar.gz": "63ec87aa7b1d457171503247004d7d046dd951992ae175423986c55f7f44aaeb",
+    "dist/2023-05-30/rustc-beta-aarch64-apple-darwin.tar.xz": "aea483c5546a038aa6381cd458f9c43d5e2e5365f3d3a296ccd3e96f90bd3fdd",
+    "dist/2023-05-30/rustc-beta-aarch64-pc-windows-msvc.tar.gz": "35e4e8c6099820f63e46ae916d9c8aa3178164856a3cde479634f0837860bf3d",
+    "dist/2023-05-30/rustc-beta-aarch64-pc-windows-msvc.tar.xz": "7232af5edf68a4d93ba7a065f2cef5b36f43d6dae76c8141c4624dd25ac17230",
+    "dist/2023-05-30/rustc-beta-aarch64-unknown-linux-gnu.tar.gz": "c08cd6ee05e23bf777c47f8eb4a66feeb85b88175360720737d96789a82906d5",
+    "dist/2023-05-30/rustc-beta-aarch64-unknown-linux-gnu.tar.xz": "025108e1db08c5f908e36f7cc5965175a008561cefbddf313501fed7bf583a44",
+    "dist/2023-05-30/rustc-beta-aarch64-unknown-linux-musl.tar.gz": "d41cec2d6001c6dc8079f4cae54c720a10288c86f6cd8e1cd362df9688ddd975",
+    "dist/2023-05-30/rustc-beta-aarch64-unknown-linux-musl.tar.xz": "81ca14bd6bd18958c9c9dc27e32dabd2a2076120d860721663fbc7339d096986",
+    "dist/2023-05-30/rustc-beta-arm-unknown-linux-gnueabi.tar.gz": "260fc42ec007adac4e885feb978f32e2624f30a87f4d91c929c3932be0dbe53c",
+    "dist/2023-05-30/rustc-beta-arm-unknown-linux-gnueabi.tar.xz": "f4b3455e84d6174a3950410cb25e753d82332ce696f9be606e6b454c279034e1",
+    "dist/2023-05-30/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz": "9f9447025db2233c4d97d92b35eae50b02db262c6b41898fa73599c245fef3e8",
+    "dist/2023-05-30/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz": "0db7a3acc6c06a41ebe93b35c62f55dc8f2526fb41e1fe546fea7746505c37a1",
+    "dist/2023-05-30/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz": "843cbc007c36850a40f4e5f0b186b2b8bf84f74385272cc2dd3e748ecfd92181",
+    "dist/2023-05-30/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz": "d56d7f0be082fe314eb85640779600fb3b74bc0f3d412a4d2c26d40671d0b116",
+    "dist/2023-05-30/rustc-beta-i686-pc-windows-gnu.tar.gz": "e2f140b4f0682fd4725862daefde019e58b3033ce1d967ec2d75a578871a36ec",
+    "dist/2023-05-30/rustc-beta-i686-pc-windows-gnu.tar.xz": "2424c4a395970e4570bd9c76396986ab68b3b81de91abc9ebe9c723b6c076d8f",
+    "dist/2023-05-30/rustc-beta-i686-pc-windows-msvc.tar.gz": "401c558d7866ad3583ab2e193bf804cff46e465d8584e6b857748edb4ef6e9e3",
+    "dist/2023-05-30/rustc-beta-i686-pc-windows-msvc.tar.xz": "ff328d754f1219ce9cdc2208d4f0feeaf88a2f1eb10cb65217ad26132ecfa67a",
+    "dist/2023-05-30/rustc-beta-i686-unknown-linux-gnu.tar.gz": "04daee6f6de28ba19ad4a0bfb83e13833e436ef381f322b4442776df885c320c",
+    "dist/2023-05-30/rustc-beta-i686-unknown-linux-gnu.tar.xz": "9ea5210272aba4d012cf195e9b36756987962700cc16911de6b17455f4fec37b",
+    "dist/2023-05-30/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz": "fb3a38a21abc89987606fcf970a748ec007b4eac2a780c9bfc78a24855dd5068",
+    "dist/2023-05-30/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz": "be03d9685ef05f5f0a5c4d2f5d1abbb4168703641c47bf449b8cead28c660b36",
+    "dist/2023-05-30/rustc-beta-mips-unknown-linux-gnu.tar.gz": "51f8f6efcfc6c09e41fb1c7bf49316650aa6fc4fba6765e9eb0f0da218a327ae",
+    "dist/2023-05-30/rustc-beta-mips-unknown-linux-gnu.tar.xz": "724ac99cebbc5dfa8e5ca2d9f32c0611f0df035b9dcd79861d9c8b6151f36d17",
+    "dist/2023-05-30/rustc-beta-mips64-unknown-linux-gnuabi64.tar.gz": "897e21ad58b01784523a18eb3e96286b956c3d62c3f8876f9831dc22543fa0f1",
+    "dist/2023-05-30/rustc-beta-mips64-unknown-linux-gnuabi64.tar.xz": "fc72123993f195910034bbc99c8099b473f77ed15345b2a2cc45669680a157b1",
+    "dist/2023-05-30/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.gz": "be642818250e94732c1f989568ea96a35befdf3be8ef5a8136de40880b9a86bf",
+    "dist/2023-05-30/rustc-beta-mips64el-unknown-linux-gnuabi64.tar.xz": "fdb42ce19f669f5a38021abb3d88edacf0d6220dd18521aa0427f683ec1ef003",
+    "dist/2023-05-30/rustc-beta-mipsel-unknown-linux-gnu.tar.gz": "47540dea37ba2885dcf8ab3456ac0e0bd193f3b40f81ea425e6acf2559a573a5",
+    "dist/2023-05-30/rustc-beta-mipsel-unknown-linux-gnu.tar.xz": "dacbb89acdf4fc587e2cccde96b14c113637f6691c1f5857322dd98b148b442f",
+    "dist/2023-05-30/rustc-beta-powerpc-unknown-linux-gnu.tar.gz": "7cf4ab6c270bea85e065b26883350173f703e266ae865e753ea45ec53775e042",
+    "dist/2023-05-30/rustc-beta-powerpc-unknown-linux-gnu.tar.xz": "4e06df0b3820503d92a4ef4782cdea2ed95b60ac4efa75e1736b8dcf360e865e",
+    "dist/2023-05-30/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz": "50e5879a296bd61545d0ed2558a28e328ad9eef6df906ec8a6ab17e98c4fc053",
+    "dist/2023-05-30/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz": "76e3e8028b6c03ece804984d3df4baf995cd09e50bebacf038fe389133f77f25",
+    "dist/2023-05-30/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz": "45070a86b9efe5a885c67dbb089a219aa7adb5b9ae7a37d115a37f75833ee598",
+    "dist/2023-05-30/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz": "02e957f9078c32d0504e15a688cefd50850428b0dad4f748a55ccba2a738c826",
+    "dist/2023-05-30/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz": "2ee8579fc0acd71b7a0ec40efecd7bd298e24c0453821c85d502e7eff4820ea1",
+    "dist/2023-05-30/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz": "758e35e9a4f1fcda8cd110cae717542768acf9f7cfef38bf8d75480b2b2e25db",
+    "dist/2023-05-30/rustc-beta-s390x-unknown-linux-gnu.tar.gz": "d3c0fbd03833f28500403d8f7f196989fa83a0c493c7c74d435c1c201912ecea",
+    "dist/2023-05-30/rustc-beta-s390x-unknown-linux-gnu.tar.xz": "d2a8e1690a1420dc3f55d43d7b190cda605f46a82882990e74157b98793e4fed",
+    "dist/2023-05-30/rustc-beta-x86_64-apple-darwin.tar.gz": "6f3d3069dc85d3d7e533904f79ebfa00e2276896ba469b75461c833aa3a1ac7a",
+    "dist/2023-05-30/rustc-beta-x86_64-apple-darwin.tar.xz": "b6e3b9eb821f861eb3c9f5687595fb9a8007f09b230f8eb38223903783658632",
+    "dist/2023-05-30/rustc-beta-x86_64-pc-windows-gnu.tar.gz": "cad6269683cc3b08ae9c0dff61ea9cee963d0654aaf60caaa4294fd8592a08a8",
+    "dist/2023-05-30/rustc-beta-x86_64-pc-windows-gnu.tar.xz": "b4cc887327b822c0dc5efb5c14e7f0d4539860f75f2af5f24755479db84b436b",
+    "dist/2023-05-30/rustc-beta-x86_64-pc-windows-msvc.tar.gz": "f6c7cb74987f13219e62389f99a409e998a340ffdd37e59b990fa5a2209d0fd5",
+    "dist/2023-05-30/rustc-beta-x86_64-pc-windows-msvc.tar.xz": "06b3fc13a7a0b938026bddbd08babb5c005f6ece5384aadf265710983243d561",
+    "dist/2023-05-30/rustc-beta-x86_64-unknown-freebsd.tar.gz": "635dfded9a7f4637af3ba390906f48f01ae1b426658bd7a7e8276db38c77fb3a",
+    "dist/2023-05-30/rustc-beta-x86_64-unknown-freebsd.tar.xz": "f385fe29efd16b08d8f0a7c71450a7880d640992d762f941468ecf57d6d6cd35",
+    "dist/2023-05-30/rustc-beta-x86_64-unknown-illumos.tar.gz": "832780952af4ff0b23b52e0654a68e314354b3a7ad6594aede927956172857d2",
+    "dist/2023-05-30/rustc-beta-x86_64-unknown-illumos.tar.xz": "262c369de160013c9a226fbeb3f2f351355ac76c7aec3dc9c4e3b85bdee7259f",
+    "dist/2023-05-30/rustc-beta-x86_64-unknown-linux-gnu.tar.gz": "08ec1e016baa2772f97dc4f51bad2fba9a31f4e78435ae62d0dc19751a1d79e3",
+    "dist/2023-05-30/rustc-beta-x86_64-unknown-linux-gnu.tar.xz": "6708643e5941765593ab043de8ebde6488473ea870ba863a3192e1a738b17ae2",
+    "dist/2023-05-30/rustc-beta-x86_64-unknown-linux-musl.tar.gz": "64cadba75ace2843303aba0c71dc1dfe27a7fe5bcf6dcbd0ba852b6b4b09eac8",
+    "dist/2023-05-30/rustc-beta-x86_64-unknown-linux-musl.tar.xz": "8357a30ac45ad29724adb68db201f05b9257de0712ffef2562ae9bbc7e2376e5",
+    "dist/2023-05-30/rustc-beta-x86_64-unknown-netbsd.tar.gz": "fb7e20647326cd2a9672d58c37f3e140c0072877f3d0a7fdfa3f728c0e1763e4",
+    "dist/2023-05-30/rustc-beta-x86_64-unknown-netbsd.tar.xz": "6eafb794492243f1a5698f3516f5c5813a9b4014693e46d2fcc6a20de7d3a58e",
+    "dist/2023-05-30/rustc-nightly-aarch64-apple-darwin.tar.gz": "237b8472a6b69ad9a3d07f28a4c8db5558774777d5f049e73f3ee47daf0ba8ff",
+    "dist/2023-05-30/rustc-nightly-aarch64-apple-darwin.tar.xz": "2bdb744db0e37fe83763742b4fdc8d8892a46a25620485cf3ef0241278aca7cc",
+    "dist/2023-05-30/rustc-nightly-aarch64-pc-windows-msvc.tar.gz": "ed67050963449f6f2ef9e64de33281cf689511aee424f345941793fcccbd9197",
+    "dist/2023-05-30/rustc-nightly-aarch64-pc-windows-msvc.tar.xz": "b90717f1d715a4488cfb95036521f21fbcf5b9f0b1c488ef44ac7854acfc9210",
+    "dist/2023-05-30/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz": "cc459d7779d32fcf51f24fc365806446bf4f3c2b4614e59181dd0696eab48f01",
+    "dist/2023-05-30/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz": "e2420872b825bd3930c426b9fd876ef1660aa7558e661175c03f5b07c1f91208",
+    "dist/2023-05-30/rustc-nightly-aarch64-unknown-linux-musl.tar.gz": "e1f1b869afa2554b2ae4981eaccf35329314161c8f427484dfb45852e6dd7e66",
+    "dist/2023-05-30/rustc-nightly-aarch64-unknown-linux-musl.tar.xz": "9f0813f8fa69d2422f234fe78c3672cf229dcaeebbd8aad83cc1242b2033c012",
+    "dist/2023-05-30/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz": "91a0bec37e3660f14be05799c4ff5241e7b0baee6d38bcc6aba446209b984d37",
+    "dist/2023-05-30/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz": "fe2798b1d67928cb05525faa420241fddacf828a6ecd07ef6374605bbb6eb07a",
+    "dist/2023-05-30/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz": "3906c8a388e57687d1bf13dcc6e22a51bc1af46bcc6731215477b80a446129fe",
+    "dist/2023-05-30/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz": "b1f20ad4a1ea551e5e34aeb6a159e66da03bfb6a2814e0a1f44c1676b579361c",
+    "dist/2023-05-30/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "69c08682db15fd941c843950811b0f367854a5f6bfeff17a810f5b2536063e2b",
+    "dist/2023-05-30/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "3fa01eb5238dcde32a33183d2022f8f81eb8bdfc29af837e581ccac796add69f",
+    "dist/2023-05-30/rustc-nightly-i686-pc-windows-gnu.tar.gz": "71af89dd66588905acc5491f837da118570180176a6f6d485e3f5585cfa308b6",
+    "dist/2023-05-30/rustc-nightly-i686-pc-windows-gnu.tar.xz": "790ba712d9b4adcc6ae5d3735386909e942ea570152a10ab4b460de5df04a7d8",
+    "dist/2023-05-30/rustc-nightly-i686-pc-windows-msvc.tar.gz": "211744f84b1e1f184b3c868c971967d0af434135dbf5445826c4a291b67ba890",
+    "dist/2023-05-30/rustc-nightly-i686-pc-windows-msvc.tar.xz": "bf3699f00cdfa130563e524513bf5b227ebf67f5807c1206bc642e69b6acd515",
+    "dist/2023-05-30/rustc-nightly-i686-unknown-linux-gnu.tar.gz": "0a16de5d417bd0c2d548e9389615137dbca6ec0c9f77c48e57af5cecc446fd6e",
+    "dist/2023-05-30/rustc-nightly-i686-unknown-linux-gnu.tar.xz": "a621cec29e1199050f533c671949164fe608ce1a2639645dec09f7c3a662afa0",
+    "dist/2023-05-30/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz": "4e9dd9734ebf981cbbc116b0dc29ab69957e8ee746aa25f71abc33553db2dc6b",
+    "dist/2023-05-30/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz": "78b5580e81ee5b5f327be718fd09bd0711271a8bba52efff1cd4ce68c4f5cd4f",
+    "dist/2023-05-30/rustc-nightly-mips-unknown-linux-gnu.tar.gz": "889308ffa2f866dc34327c0f20195e33a3c1e8124a19635918b0a8e5220ea56d",
+    "dist/2023-05-30/rustc-nightly-mips-unknown-linux-gnu.tar.xz": "74da26ff0692a4cb1c84f3cd42c9a8c756cb588eaa40cfbfc6dbc9cbc5f018e9",
+    "dist/2023-05-30/rustc-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "1aec9abde4a1e9e042191b06848d262848c54b448ddba00c9c736207953140b3",
+    "dist/2023-05-30/rustc-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "a046b49cb6ec60ecaa8ed60f6c77b60b3d0cfa76cfd7e48b6b2a808e4d8a8e51",
+    "dist/2023-05-30/rustc-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "e6dfbe2df31c26d0df8ae413f41705039bc41f567dc8f4e81b9e908a61157d08",
+    "dist/2023-05-30/rustc-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "b4285b27d8ee3325ce4cc3755182d159376fbe93aa14d3adfeb06b5fb20ebdce",
+    "dist/2023-05-30/rustc-nightly-mipsel-unknown-linux-gnu.tar.gz": "62de5f6093791c80744267f492a0ba58f998f3e826933a396e21efba7e88ea1d",
+    "dist/2023-05-30/rustc-nightly-mipsel-unknown-linux-gnu.tar.xz": "3240f8ffa7bef40dfb2a19a1029a4b5733403c9cc94bcf7f0a66e0134e2b93fe",
+    "dist/2023-05-30/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz": "49f9fa5a9d3c07365a29d0dd0ac94df9ef8c7f9713724a39ade6040bb1a4a627",
+    "dist/2023-05-30/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz": "285b2c228c4a37dc6f5ced5c585631e2166b43c0b76bb794139f0aa690013a13",
+    "dist/2023-05-30/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz": "bcd1c9b4d1efd109bf29b2005f35931b92f9675ced5b71a6dcfb10bac1ed87af",
+    "dist/2023-05-30/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz": "7f61eef3681bb1bcc285910e596c4e11c62aca0ed1d7eb9de75fa0822ca89ecb",
+    "dist/2023-05-30/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "278473fbd38e2d395257f90bc84010e44ade32cb35a249fa0d32e92c174e9776",
+    "dist/2023-05-30/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "215a805efcfc898e3ae7cfeda427e10d252434175d8eb70613664ac84c1e38ff",
+    "dist/2023-05-30/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "3ba38b376d5c58324221466dddc95ce0917f7bcf6a7cca8c187ff999abd8f74d",
+    "dist/2023-05-30/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "d52cba02774a256db1cd40ef3c9fee10431f8ef9a738553373474bb629d8c108",
+    "dist/2023-05-30/rustc-nightly-s390x-unknown-linux-gnu.tar.gz": "4dca59e9d10f07e60bb8f522f4b97c2a8de8e186679bdc8e85a105bfba80c38d",
+    "dist/2023-05-30/rustc-nightly-s390x-unknown-linux-gnu.tar.xz": "e0d07c8f2605600d88d901dc2837c01266d28064f57e1ba7a3946a59a249b37d",
+    "dist/2023-05-30/rustc-nightly-x86_64-apple-darwin.tar.gz": "aef9c49ef3496a23567eef639f54131fd54fdedc092d39d89c7da8e41f97b100",
+    "dist/2023-05-30/rustc-nightly-x86_64-apple-darwin.tar.xz": "c78201af204ed99ae67c5f8747a1495b58e6a2b2c92a9290e703553c0fc4820a",
+    "dist/2023-05-30/rustc-nightly-x86_64-pc-windows-gnu.tar.gz": "70ff64b7f28be159fec7e518d3787e836c1a7f5a88177742215e46269a29b4aa",
+    "dist/2023-05-30/rustc-nightly-x86_64-pc-windows-gnu.tar.xz": "939bf932d60e2d343d4e00bbc48e10eb57755de14729795bd6965cf23eed74f5",
+    "dist/2023-05-30/rustc-nightly-x86_64-pc-windows-msvc.tar.gz": "e20748dcca42a84031bf2eae7a61d3b0619c383dca274287824a15c982b42bf3",
+    "dist/2023-05-30/rustc-nightly-x86_64-pc-windows-msvc.tar.xz": "4687e53fcbe7487647b876b36efca97f9b83389f35d317a76b601d43edd54c00",
+    "dist/2023-05-30/rustc-nightly-x86_64-unknown-freebsd.tar.gz": "c662f8f489ec8be2ed2066140a7b40ef92ac393103e2de43a683918ec81c3ab1",
+    "dist/2023-05-30/rustc-nightly-x86_64-unknown-freebsd.tar.xz": "b350dd8bd95563cf9a422bac6fd4ac44d21186324a9cda4998e5b676c9646b7e",
+    "dist/2023-05-30/rustc-nightly-x86_64-unknown-illumos.tar.gz": "18396eaa0c44555bfd550018671a4ca07a2c890e08ab8a6e71e224256f01bc61",
+    "dist/2023-05-30/rustc-nightly-x86_64-unknown-illumos.tar.xz": "97af9014bdd6b758b7dfaacc868f91c62729ddc70f6b766f78926d46098dc610",
+    "dist/2023-05-30/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz": "9bb5775dce7c5659ba983c1581290f3d29cab54e2e28fbeb0a89b076bce24969",
+    "dist/2023-05-30/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz": "9a2bf45136801dbb04b2cb6f7db45b731ff38d9f285c55270a2399184a422e5e",
+    "dist/2023-05-30/rustc-nightly-x86_64-unknown-linux-musl.tar.gz": "355e65949a17cb71b582e3a3a51a4a68c25fa1f07c5d02604869d0e1a3e83274",
+    "dist/2023-05-30/rustc-nightly-x86_64-unknown-linux-musl.tar.xz": "afbd2923484621716ff241998b6c4c6c3d7023e00c1f1bf94ac15e3072c15c91",
+    "dist/2023-05-30/rustc-nightly-x86_64-unknown-netbsd.tar.gz": "d9d79bff98b3a5bd95aab8735a3656c494d2d275afbe313f1d1adececb82f1e0",
+    "dist/2023-05-30/rustc-nightly-x86_64-unknown-netbsd.tar.xz": "a92f1dea5d4f811bd81a297e6b45c5253948956fa835efcbfb3174ca45cbc812",
+    "dist/2023-05-30/rustfmt-nightly-aarch64-apple-darwin.tar.gz": "59b1ecc2a0cc0dd289f58e14ec8d812cba3906a486b53d991e9d61fb1aace497",
+    "dist/2023-05-30/rustfmt-nightly-aarch64-apple-darwin.tar.xz": "89c70ea18ce719c8171190cca97b3f5c641999ef54952b4f0f426c05c63af698",
+    "dist/2023-05-30/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz": "164378266ab65a8d6464e914ff2dca848d6f044362bc81c38b260e52e1856147",
+    "dist/2023-05-30/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz": "b44fdc2708def8e02cf7f39e228c6698c2e0eee217cc02d60ee731859826b544",
+    "dist/2023-05-30/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz": "0d34a3f499eb7d2819090c4b923df26462d12f6261327a03a3df61af3346467f",
+    "dist/2023-05-30/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz": "add3cde0b9771e78c35f9eae1d91fe1aec94e5b255e3d741c80916dabf23d214",
+    "dist/2023-05-30/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz": "95f05d6549a3618e49b1607a04f9814aa55cb393b8c662a67dbd0909b65d9e45",
+    "dist/2023-05-30/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz": "e4e8ab74aa90355142d16d677452a6b17b99fe2c26c3e7d19541c00d316a9a1c",
+    "dist/2023-05-30/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz": "891fcd1496565388160c70030f098eae9725423a726d25cb95f81c8a5e9a7fd0",
+    "dist/2023-05-30/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz": "330afd31d6ef259a73f365bd57c2c8cc27f972f475519b880065ef9bbbef4417",
+    "dist/2023-05-30/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz": "32087f3a53706c8daeea8ee80afb16e60968cd653404e7ed98322d998b83582d",
+    "dist/2023-05-30/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz": "e2fe133066904154fa773a4731efbf77d46631413b77beea6ecb8f3617b0dedb",
+    "dist/2023-05-30/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz": "df28a8a4b90c71b9542f1327d3138d9b13caddd5bd7a3738b09aafa75480f20f",
+    "dist/2023-05-30/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz": "c9dabd1e26f6c94e3a2162c02bd83cc6c80cf41f075d970480fd8fa6c94f170d",
+    "dist/2023-05-30/rustfmt-nightly-i686-pc-windows-gnu.tar.gz": "b3eaa34bc2441a227de9646a1f90480cb934592e919944e2feae31be0d048f1e",
+    "dist/2023-05-30/rustfmt-nightly-i686-pc-windows-gnu.tar.xz": "dd3efd26ddf45d4366fa6c6f024e0223329c378887b636be70d89951feeb223d",
+    "dist/2023-05-30/rustfmt-nightly-i686-pc-windows-msvc.tar.gz": "50c1f997d3b7b47f0eea36397252646fe97c484345afe3c08938915bf46b1286",
+    "dist/2023-05-30/rustfmt-nightly-i686-pc-windows-msvc.tar.xz": "8da362db734f58f99d3616b3a6d0e2e0976f634bc457143fd627993a2a43cd41",
+    "dist/2023-05-30/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz": "bb6b790c57de3157370ec6dfb3d5c6a3e47d4a7f483d716c04ddeb6a1d370470",
+    "dist/2023-05-30/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz": "e83bea6b615680a2d1aff31a0302fceefe970d4d801d61c76bb59d61e16235ba",
+    "dist/2023-05-30/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz": "3c45423d2fee0fb2218e80760910f0f3344f67cb867e746e2bc825f74a4dad35",
+    "dist/2023-05-30/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz": "c3fbb683e848927b800933799d93ce9f47e3712a650e0b2462830e91fd62ec2d",
+    "dist/2023-05-30/rustfmt-nightly-mips-unknown-linux-gnu.tar.gz": "f795bf82973e3d6ae90d5bfd17c3a2326dd91c787d5638fd5e0d3091fc2bd738",
+    "dist/2023-05-30/rustfmt-nightly-mips-unknown-linux-gnu.tar.xz": "404217de3ead2226ba192fc2ee3a9928653272dd1b05774ae735bdf2db9596e0",
+    "dist/2023-05-30/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.gz": "f62319f4429680866c6c55c9928f864fcd478dd71b16909186aa9a14d6d4b4e6",
+    "dist/2023-05-30/rustfmt-nightly-mips64-unknown-linux-gnuabi64.tar.xz": "caf648cf2d71b67393ef068715f974f43aa6d80eb6a6040b31d496d64d31b12e",
+    "dist/2023-05-30/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.gz": "e11962a76505c523d210bafa0a87e10f09bf28350149a11091222678acef9b2b",
+    "dist/2023-05-30/rustfmt-nightly-mips64el-unknown-linux-gnuabi64.tar.xz": "daadb0973b1acded5fbc32ba2aa4974ff25ca2cd90afa5eaecdea51ef55bf154",
+    "dist/2023-05-30/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.gz": "c501a1fd769e826eac68ba1bb14feb384236f7d87f5d3fe1d6f2373b0fb3f966",
+    "dist/2023-05-30/rustfmt-nightly-mipsel-unknown-linux-gnu.tar.xz": "c1af630b9367b3c93d5bec0a5b4d7c3befa0d3036ca3fdd5d453b04bb74e239c",
+    "dist/2023-05-30/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz": "cbda874bd604c078fe023a3c4dd480cc537a3dfdf0bc5eb8f55a1e5a21691915",
+    "dist/2023-05-30/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz": "d795e96e1303d1a0057aabc079b0258a54361bdcf2359b2c096966098e950e57",
+    "dist/2023-05-30/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz": "5b699b2d9c77548d4ada3847996e0f4cf94446cb553ad9447aca2673e99c4948",
+    "dist/2023-05-30/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz": "39d7f7df56f1c5a92b41ad2e40ab570bee861006cdf9b93aa11b967906c60828",
+    "dist/2023-05-30/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz": "c745fd0580669e901d56e81050b6447e4cf7743da32e6ea95607511d9c3201d1",
+    "dist/2023-05-30/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz": "b360a343cb0f9e36ca9fe03d77047d600a16907416fa1e5c0cb7a4611fc5c3f2",
+    "dist/2023-05-30/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz": "5a98c28cc95008522ace67fd15a9e5d71b1b969f0ec2410aaadfeda618aed1be",
+    "dist/2023-05-30/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz": "5197422b4ef7ce51777c020f74a5fb7edc01339fcb9b31bbf9781195639794fa",
+    "dist/2023-05-30/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz": "6f6acce9edb006b355770f3934eba4c15b10f205164e49c587b6f9e60924ed99",
+    "dist/2023-05-30/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz": "1e1ebec2d56706f37afaaa23ed940e8953b5207280e83bfd0acce4a149416911",
+    "dist/2023-05-30/rustfmt-nightly-x86_64-apple-darwin.tar.gz": "c1ea49dac64b7872dd194db925cda89efa596808d993dedacc8be042d529c2de",
+    "dist/2023-05-30/rustfmt-nightly-x86_64-apple-darwin.tar.xz": "ddf1cd4e32ce497187f79f34edf346f6db31e9d50d2cf1870fc1f2edfbadbcdd",
+    "dist/2023-05-30/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz": "cb5d566d5b6dc6f94cd7015ad1d8074edc0fdff67e4099df7adaf0251f729d8d",
+    "dist/2023-05-30/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz": "086ef160c92e5c3eaf887b2f28d54562e7916be4758b7b9798019f5aa23f02b1",
+    "dist/2023-05-30/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz": "5447f33f134487147df663680741f94e2d58c45495dee33e16052bacf74975de",
+    "dist/2023-05-30/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz": "78104f5ecb2ac790c3958a5331316580991c7a03f1258a72b7c43f660f955461",
+    "dist/2023-05-30/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz": "e3da153242be44fd656f4bfe33371cf7b874e220698cedac207f14ce790c7a66",
+    "dist/2023-05-30/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz": "cc9c83b6dade84d6dcf390701d7cbd2613915d9af68b08e68b9ff1d72e742248",
+    "dist/2023-05-30/rustfmt-nightly-x86_64-unknown-illumos.tar.gz": "e0d3aeb40a6139c56000d5b8a8693aafad105d05ccb8cebb026e383da59baae6",
+    "dist/2023-05-30/rustfmt-nightly-x86_64-unknown-illumos.tar.xz": "96981188f60cf8dc05a6b39788f0348b57d3972961b0a2d0b5759dbfc4c7d345",
+    "dist/2023-05-30/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz": "dfed96134506c80e8c503719c7502310b17bee6d3c963764af9dc70c5721795f",
+    "dist/2023-05-30/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz": "36fb2a16bba51b765be6c82b57fccc6664699d3e476d7cd3d56c71b80c6f2c78",
+    "dist/2023-05-30/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz": "b0ea71d0f3fb18f95fe0801261ff28e9b25ff9078d8cf1c2122ac515841af2ee",
+    "dist/2023-05-30/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz": "9f03b6aab46560698e507796541d0c0347c5bffb4fb984ea6c7dc73f479c8d81",
+    "dist/2023-05-30/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz": "0c473e1e4cd1b8096e03f10d13f8e640e88a002ec798790c7423074ff49168c8",
+    "dist/2023-05-30/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz": "6da959be0b1c6d1fb6e56ad88672ee817b8827b8210cefd897e5aca085b2c32d"
   }
 }
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_ref_to_mut.rs b/src/tools/clippy/clippy_lints/src/casts/cast_ref_to_mut.rs
deleted file mode 100644
index 15f2f81f407..00000000000
--- a/src/tools/clippy/clippy_lints/src/casts/cast_ref_to_mut.rs
+++ /dev/null
@@ -1,26 +0,0 @@
-use clippy_utils::diagnostics::span_lint;
-use if_chain::if_chain;
-use rustc_hir::{Expr, ExprKind, MutTy, Mutability, TyKind, UnOp};
-use rustc_lint::LateContext;
-use rustc_middle::ty;
-
-use super::CAST_REF_TO_MUT;
-
-pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
-    if_chain! {
-        if let ExprKind::Unary(UnOp::Deref, e) = &expr.kind;
-        if let ExprKind::Cast(e, t) = &e.kind;
-        if let TyKind::Ptr(MutTy { mutbl: Mutability::Mut, .. }) = t.kind;
-        if let ExprKind::Cast(e, t) = &e.kind;
-        if let TyKind::Ptr(MutTy { mutbl: Mutability::Not, .. }) = t.kind;
-        if let ty::Ref(..) = cx.typeck_results().node_type(e.hir_id).kind();
-        then {
-            span_lint(
-                cx,
-                CAST_REF_TO_MUT,
-                expr.span,
-                "casting `&T` to `&mut T` may cause undefined behavior, consider instead using an `UnsafeCell`",
-            );
-        }
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/casts/mod.rs b/src/tools/clippy/clippy_lints/src/casts/mod.rs
index cfeb75eed3b..0c175372aab 100644
--- a/src/tools/clippy/clippy_lints/src/casts/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/casts/mod.rs
@@ -9,7 +9,6 @@ mod cast_possible_truncation;
 mod cast_possible_wrap;
 mod cast_precision_loss;
 mod cast_ptr_alignment;
-mod cast_ref_to_mut;
 mod cast_sign_loss;
 mod cast_slice_different_sizes;
 mod cast_slice_from_raw_parts;
@@ -332,41 +331,6 @@ declare_clippy_lint! {
 
 declare_clippy_lint! {
     /// ### What it does
-    /// Checks for casts of `&T` to `&mut T` anywhere in the code.
-    ///
-    /// ### Why is this bad?
-    /// It’s basically guaranteed to be undefined behavior.
-    /// `UnsafeCell` is the only way to obtain aliasable data that is considered
-    /// mutable.
-    ///
-    /// ### Example
-    /// ```rust,ignore
-    /// fn x(r: &i32) {
-    ///     unsafe {
-    ///         *(r as *const _ as *mut _) += 1;
-    ///     }
-    /// }
-    /// ```
-    ///
-    /// Instead consider using interior mutability types.
-    ///
-    /// ```rust
-    /// use std::cell::UnsafeCell;
-    ///
-    /// fn x(r: &UnsafeCell<i32>) {
-    ///     unsafe {
-    ///         *r.get() += 1;
-    ///     }
-    /// }
-    /// ```
-    #[clippy::version = "1.33.0"]
-    pub CAST_REF_TO_MUT,
-    correctness,
-    "a cast of reference to a mutable pointer"
-}
-
-declare_clippy_lint! {
-    /// ### What it does
     /// Checks for expressions where a character literal is cast
     /// to `u8` and suggests using a byte literal instead.
     ///
@@ -680,7 +644,6 @@ impl_lint_pass!(Casts => [
     CAST_POSSIBLE_TRUNCATION,
     CAST_POSSIBLE_WRAP,
     CAST_LOSSLESS,
-    CAST_REF_TO_MUT,
     CAST_PTR_ALIGNMENT,
     CAST_SLICE_DIFFERENT_SIZES,
     UNNECESSARY_CAST,
@@ -747,7 +710,6 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
             }
         }
 
-        cast_ref_to_mut::check(cx, expr);
         cast_ptr_alignment::check(cx, expr);
         char_lit_as_u8::check(cx, expr);
         ptr_as_ptr::check(cx, expr, &self.msrv);
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 0ae95b045e0..212e809d4c5 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -81,7 +81,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::casts::CAST_POSSIBLE_WRAP_INFO,
     crate::casts::CAST_PRECISION_LOSS_INFO,
     crate::casts::CAST_PTR_ALIGNMENT_INFO,
-    crate::casts::CAST_REF_TO_MUT_INFO,
     crate::casts::CAST_SIGN_LOSS_INFO,
     crate::casts::CAST_SLICE_DIFFERENT_SIZES_INFO,
     crate::casts::CAST_SLICE_FROM_RAW_PARTS_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/renamed_lints.rs b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
index 7c2a100efda..4cb41830023 100644
--- a/src/tools/clippy/clippy_lints/src/renamed_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
@@ -31,6 +31,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
     ("clippy::stutter", "clippy::module_name_repetitions"),
     ("clippy::to_string_in_display", "clippy::recursive_format_impl"),
     ("clippy::zero_width_space", "clippy::invisible_characters"),
+    ("clippy::cast_ref_to_mut", "cast_ref_to_mut"),
     ("clippy::clone_double_ref", "suspicious_double_ref_op"),
     ("clippy::drop_bounds", "drop_bounds"),
     ("clippy::drop_copy", "dropping_copy_types"),
diff --git a/src/tools/clippy/tests/ui/cast_ref_to_mut.rs b/src/tools/clippy/tests/ui/cast_ref_to_mut.rs
deleted file mode 100644
index c48a734ba32..00000000000
--- a/src/tools/clippy/tests/ui/cast_ref_to_mut.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-#![warn(clippy::cast_ref_to_mut)]
-#![allow(clippy::no_effect, clippy::borrow_as_ptr)]
-
-extern "C" {
-    // N.B., mutability can be easily incorrect in FFI calls -- as
-    // in C, the default is mutable pointers.
-    fn ffi(c: *mut u8);
-    fn int_ffi(c: *mut i32);
-}
-
-fn main() {
-    let s = String::from("Hello");
-    let a = &s;
-    unsafe {
-        let num = &3i32;
-        let mut_num = &mut 3i32;
-        // Should be warned against
-        (*(a as *const _ as *mut String)).push_str(" world");
-        *(a as *const _ as *mut _) = String::from("Replaced");
-        *(a as *const _ as *mut String) += " world";
-        // Shouldn't be warned against
-        println!("{}", *(num as *const _ as *const i16));
-        println!("{}", *(mut_num as *mut _ as *mut i16));
-        ffi(a.as_ptr() as *mut _);
-        int_ffi(num as *const _ as *mut _);
-        int_ffi(&3 as *const _ as *mut _);
-        let mut value = 3;
-        let value: *const i32 = &mut value;
-        *(value as *const i16 as *mut i16) = 42;
-    }
-}
diff --git a/src/tools/clippy/tests/ui/cast_ref_to_mut.stderr b/src/tools/clippy/tests/ui/cast_ref_to_mut.stderr
deleted file mode 100644
index aacd99437d9..00000000000
--- a/src/tools/clippy/tests/ui/cast_ref_to_mut.stderr
+++ /dev/null
@@ -1,22 +0,0 @@
-error: casting `&T` to `&mut T` may cause undefined behavior, consider instead using an `UnsafeCell`
-  --> $DIR/cast_ref_to_mut.rs:18:9
-   |
-LL |         (*(a as *const _ as *mut String)).push_str(" world");
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `-D clippy::cast-ref-to-mut` implied by `-D warnings`
-
-error: casting `&T` to `&mut T` may cause undefined behavior, consider instead using an `UnsafeCell`
-  --> $DIR/cast_ref_to_mut.rs:19:9
-   |
-LL |         *(a as *const _ as *mut _) = String::from("Replaced");
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: casting `&T` to `&mut T` may cause undefined behavior, consider instead using an `UnsafeCell`
-  --> $DIR/cast_ref_to_mut.rs:20:9
-   |
-LL |         *(a as *const _ as *mut String) += " world";
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
-
diff --git a/src/tools/clippy/tests/ui/modulo_one.stderr b/src/tools/clippy/tests/ui/modulo_one.stderr
index 04ecdef5e99..83a76f81d4e 100644
--- a/src/tools/clippy/tests/ui/modulo_one.stderr
+++ b/src/tools/clippy/tests/ui/modulo_one.stderr
@@ -2,7 +2,7 @@ error: this operation will panic at runtime
   --> $DIR/modulo_one.rs:11:5
    |
 LL |     i32::MIN % (-1); // also caught by rustc
-   |     ^^^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow
+   |     ^^^^^^^^^^^^^^^ attempt to compute `i32::MIN % -1_i32`, which would overflow
    |
    = note: `#[deny(unconditional_panic)]` on by default
 
@@ -10,13 +10,13 @@ error: this operation will panic at runtime
   --> $DIR/modulo_one.rs:21:5
    |
 LL |     INT_MIN % NEG_ONE; // also caught by rustc
-   |     ^^^^^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow
+   |     ^^^^^^^^^^^^^^^^^ attempt to compute `i64::MIN % -1_i64`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/modulo_one.rs:22:5
    |
 LL |     INT_MIN % STATIC_NEG_ONE; // ONLY caught by rustc
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i64::MIN % -1_i64`, which would overflow
 
 error: any number modulo 1 will be 0
   --> $DIR/modulo_one.rs:8:5
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index 53ac65473b8..f7854b89ee4 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -29,6 +29,7 @@
 #![allow(clippy::recursive_format_impl)]
 #![allow(clippy::invisible_characters)]
 #![allow(suspicious_double_ref_op)]
+#![allow(cast_ref_to_mut)]
 #![allow(drop_bounds)]
 #![allow(dropping_copy_types)]
 #![allow(dropping_references)]
@@ -76,6 +77,7 @@
 #![warn(clippy::module_name_repetitions)]
 #![warn(clippy::recursive_format_impl)]
 #![warn(clippy::invisible_characters)]
+#![warn(cast_ref_to_mut)]
 #![warn(suspicious_double_ref_op)]
 #![warn(drop_bounds)]
 #![warn(dropping_copy_types)]
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index 722c0b3eb27..fa347d395ef 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -29,6 +29,7 @@
 #![allow(clippy::recursive_format_impl)]
 #![allow(clippy::invisible_characters)]
 #![allow(suspicious_double_ref_op)]
+#![allow(cast_ref_to_mut)]
 #![allow(drop_bounds)]
 #![allow(dropping_copy_types)]
 #![allow(dropping_references)]
@@ -76,6 +77,7 @@
 #![warn(clippy::stutter)]
 #![warn(clippy::to_string_in_display)]
 #![warn(clippy::zero_width_space)]
+#![warn(clippy::cast_ref_to_mut)]
 #![warn(clippy::clone_double_ref)]
 #![warn(clippy::drop_bounds)]
 #![warn(clippy::drop_copy)]
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index 1ff83917660..9dffe51e5d7 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -1,5 +1,5 @@
 error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
-  --> $DIR/rename.rs:50:9
+  --> $DIR/rename.rs:51:9
    |
 LL | #![warn(clippy::almost_complete_letter_range)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
@@ -7,292 +7,298 @@ LL | #![warn(clippy::almost_complete_letter_range)]
    = note: `-D renamed-and-removed-lints` implied by `-D warnings`
 
 error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
-  --> $DIR/rename.rs:51:9
+  --> $DIR/rename.rs:52:9
    |
 LL | #![warn(clippy::blacklisted_name)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
 
 error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:52:9
+  --> $DIR/rename.rs:53:9
    |
 LL | #![warn(clippy::block_in_if_condition_expr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:53:9
+  --> $DIR/rename.rs:54:9
    |
 LL | #![warn(clippy::block_in_if_condition_stmt)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
-  --> $DIR/rename.rs:54:9
+  --> $DIR/rename.rs:55:9
    |
 LL | #![warn(clippy::box_vec)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
 
 error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
-  --> $DIR/rename.rs:55:9
+  --> $DIR/rename.rs:56:9
    |
 LL | #![warn(clippy::const_static_lifetime)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
 
 error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
-  --> $DIR/rename.rs:56:9
+  --> $DIR/rename.rs:57:9
    |
 LL | #![warn(clippy::cyclomatic_complexity)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
 
 error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
-  --> $DIR/rename.rs:57:9
+  --> $DIR/rename.rs:58:9
    |
 LL | #![warn(clippy::derive_hash_xor_eq)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
 
 error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
-  --> $DIR/rename.rs:58:9
+  --> $DIR/rename.rs:59:9
    |
 LL | #![warn(clippy::disallowed_method)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
 
 error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
-  --> $DIR/rename.rs:59:9
+  --> $DIR/rename.rs:60:9
    |
 LL | #![warn(clippy::disallowed_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
 
 error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
-  --> $DIR/rename.rs:60:9
+  --> $DIR/rename.rs:61:9
    |
 LL | #![warn(clippy::eval_order_dependence)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
 
 error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
-  --> $DIR/rename.rs:61:9
+  --> $DIR/rename.rs:62:9
    |
 LL | #![warn(clippy::identity_conversion)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
 
 error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
-  --> $DIR/rename.rs:62:9
+  --> $DIR/rename.rs:63:9
    |
 LL | #![warn(clippy::if_let_some_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
 
 error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
-  --> $DIR/rename.rs:63:9
+  --> $DIR/rename.rs:64:9
    |
 LL | #![warn(clippy::integer_arithmetic)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
 
 error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
-  --> $DIR/rename.rs:64:9
+  --> $DIR/rename.rs:65:9
    |
 LL | #![warn(clippy::logic_bug)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
 
 error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
-  --> $DIR/rename.rs:65:9
+  --> $DIR/rename.rs:66:9
    |
 LL | #![warn(clippy::new_without_default_derive)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
 
 error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
-  --> $DIR/rename.rs:66:9
+  --> $DIR/rename.rs:67:9
    |
 LL | #![warn(clippy::option_and_then_some)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
 
 error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:67:9
+  --> $DIR/rename.rs:68:9
    |
 LL | #![warn(clippy::option_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:68:9
+  --> $DIR/rename.rs:69:9
    |
 LL | #![warn(clippy::option_map_unwrap_or)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:69:9
+  --> $DIR/rename.rs:70:9
    |
 LL | #![warn(clippy::option_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:70:9
+  --> $DIR/rename.rs:71:9
    |
 LL | #![warn(clippy::option_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
-  --> $DIR/rename.rs:71:9
+  --> $DIR/rename.rs:72:9
    |
 LL | #![warn(clippy::ref_in_deref)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
 
 error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:72:9
+  --> $DIR/rename.rs:73:9
    |
 LL | #![warn(clippy::result_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:73:9
+  --> $DIR/rename.rs:74:9
    |
 LL | #![warn(clippy::result_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:74:9
+  --> $DIR/rename.rs:75:9
    |
 LL | #![warn(clippy::result_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
-  --> $DIR/rename.rs:75:9
+  --> $DIR/rename.rs:76:9
    |
 LL | #![warn(clippy::single_char_push_str)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
 
 error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
-  --> $DIR/rename.rs:76:9
+  --> $DIR/rename.rs:77:9
    |
 LL | #![warn(clippy::stutter)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
 
 error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
-  --> $DIR/rename.rs:77:9
+  --> $DIR/rename.rs:78:9
    |
 LL | #![warn(clippy::to_string_in_display)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
 
 error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
-  --> $DIR/rename.rs:78:9
+  --> $DIR/rename.rs:79:9
    |
 LL | #![warn(clippy::zero_width_space)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
 
+error: lint `clippy::cast_ref_to_mut` has been renamed to `cast_ref_to_mut`
+  --> $DIR/rename.rs:80:9
+   |
+LL | #![warn(clippy::cast_ref_to_mut)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `cast_ref_to_mut`
+
 error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
-  --> $DIR/rename.rs:79:9
+  --> $DIR/rename.rs:81:9
    |
 LL | #![warn(clippy::clone_double_ref)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
 
 error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-  --> $DIR/rename.rs:80:9
+  --> $DIR/rename.rs:82:9
    |
 LL | #![warn(clippy::drop_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
 
 error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
-  --> $DIR/rename.rs:81:9
+  --> $DIR/rename.rs:83:9
    |
 LL | #![warn(clippy::drop_copy)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
 
 error: lint `clippy::drop_ref` has been renamed to `dropping_references`
-  --> $DIR/rename.rs:82:9
+  --> $DIR/rename.rs:84:9
    |
 LL | #![warn(clippy::drop_ref)]
    |         ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
 
 error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:83:9
+  --> $DIR/rename.rs:85:9
    |
 LL | #![warn(clippy::for_loop_over_option)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:84:9
+  --> $DIR/rename.rs:86:9
    |
 LL | #![warn(clippy::for_loop_over_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:85:9
+  --> $DIR/rename.rs:87:9
    |
 LL | #![warn(clippy::for_loops_over_fallibles)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
-  --> $DIR/rename.rs:86:9
+  --> $DIR/rename.rs:88:9
    |
 LL | #![warn(clippy::forget_copy)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
 
 error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
-  --> $DIR/rename.rs:87:9
+  --> $DIR/rename.rs:89:9
    |
 LL | #![warn(clippy::forget_ref)]
    |         ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
 
 error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-  --> $DIR/rename.rs:88:9
+  --> $DIR/rename.rs:90:9
    |
 LL | #![warn(clippy::into_iter_on_array)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
 
 error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
-  --> $DIR/rename.rs:89:9
+  --> $DIR/rename.rs:91:9
    |
 LL | #![warn(clippy::invalid_atomic_ordering)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
 
 error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
-  --> $DIR/rename.rs:90:9
+  --> $DIR/rename.rs:92:9
    |
 LL | #![warn(clippy::invalid_ref)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
 
 error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked`
-  --> $DIR/rename.rs:91:9
+  --> $DIR/rename.rs:93:9
    |
 LL | #![warn(clippy::invalid_utf8_in_unchecked)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked`
 
 error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
-  --> $DIR/rename.rs:92:9
+  --> $DIR/rename.rs:94:9
    |
 LL | #![warn(clippy::let_underscore_drop)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
 
 error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
-  --> $DIR/rename.rs:93:9
+  --> $DIR/rename.rs:95:9
    |
 LL | #![warn(clippy::mem_discriminant_non_enum)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
 
 error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
-  --> $DIR/rename.rs:94:9
+  --> $DIR/rename.rs:96:9
    |
 LL | #![warn(clippy::panic_params)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
 
 error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
-  --> $DIR/rename.rs:95:9
+  --> $DIR/rename.rs:97:9
    |
 LL | #![warn(clippy::positional_named_format_parameters)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
 
 error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
-  --> $DIR/rename.rs:96:9
+  --> $DIR/rename.rs:98:9
    |
 LL | #![warn(clippy::temporary_cstring_as_ptr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
 
 error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
-  --> $DIR/rename.rs:97:9
+  --> $DIR/rename.rs:99:9
    |
 LL | #![warn(clippy::unknown_clippy_lints)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
 
 error: lint `clippy::unused_label` has been renamed to `unused_labels`
-  --> $DIR/rename.rs:98:9
+  --> $DIR/rename.rs:100:9
    |
 LL | #![warn(clippy::unused_label)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
 
-error: aborting due to 49 previous errors
+error: aborting due to 50 previous errors
 
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index a799d93ce25..923b2e63f2e 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1939,6 +1939,17 @@ impl<'test> TestCx<'test> {
         // Use a single thread for efficiency and a deterministic error message order
         rustc.arg("-Zthreads=1");
 
+        // Hide libstd sources from ui tests to make sure we generate the stderr
+        // output that users will see.
+        // Without this, we may be producing good diagnostics in-tree but users
+        // will not see half the information.
+        //
+        // This also has the benefit of more effectively normalizing output between different
+        // compilers, so that we don't have to know the `/rustc/$sha` output to normalize after the
+        // fact.
+        rustc.arg("-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX");
+        rustc.arg("-Ztranslate-remapped-path-to-local-path=no");
+
         // Optionally prevent default --sysroot if specified in test compile-flags.
         if !self.props.compile_flags.iter().any(|flag| flag.starts_with("--sysroot")) {
             // In stage 0, make sure we use `stage0-sysroot` instead of the bootstrap sysroot.
@@ -2014,13 +2025,6 @@ impl<'test> TestCx<'test> {
                 rustc.arg("-Ccodegen-units=1");
                 // Hide line numbers to reduce churn
                 rustc.arg("-Zui-testing");
-                // Hide libstd sources from ui tests to make sure we generate the stderr
-                // output that users will see.
-                // Without this, we may be producing good diagnostics in-tree but users
-                // will not see half the information.
-                rustc.arg("-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX");
-                rustc.arg("-Ztranslate-remapped-path-to-local-path=no");
-
                 rustc.arg("-Zdeduplicate-diagnostics=no");
                 // FIXME: use this for other modes too, for perf?
                 rustc.arg("-Cstrip=debuginfo");
@@ -3732,28 +3736,13 @@ impl<'test> TestCx<'test> {
             normalize_path(&remapped_parent_dir, "$DIR");
         }
 
-        let source_bases = &[
-            // Source base on the current filesystem (calculated as parent of `tests/$suite`):
-            Some(self.config.src_base.parent().unwrap().parent().unwrap().into()),
-            // Source base on the sysroot (from the src components downloaded by `download-rustc`):
-            Some(self.config.sysroot_base.join("lib").join("rustlib").join("src").join("rust")),
-            // Virtual `/rustc/$sha` remapped paths (if `remap-debuginfo` is enabled):
-            option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").map(PathBuf::from),
-            // Virtual `/rustc/$sha` coming from download-rustc:
-            std::env::var_os("FAKE_DOWNLOAD_RUSTC_PREFIX").map(PathBuf::from),
-            // Tests using -Zsimulate-remapped-rust-src-base should use this fake path
-            Some("/rustc/FAKE_PREFIX".into()),
-        ];
-        for base_dir in source_bases {
-            if let Some(base_dir) = base_dir {
-                // Paths into the libstd/libcore
-                normalize_path(&base_dir.join("library"), "$SRC_DIR");
-                // `ui-fulldeps` tests can show paths to the compiler source when testing macros from
-                // `rustc_macros`
-                // eg. /home/user/rust/compiler
-                normalize_path(&base_dir.join("compiler"), "$COMPILER_DIR");
-            }
-        }
+        let base_dir = Path::new("/rustc/FAKE_PREFIX");
+        // Paths into the libstd/libcore
+        normalize_path(&base_dir.join("library"), "$SRC_DIR");
+        // `ui-fulldeps` tests can show paths to the compiler source when testing macros from
+        // `rustc_macros`
+        // eg. /home/user/rust/compiler
+        normalize_path(&base_dir.join("compiler"), "$COMPILER_DIR");
 
         // Paths into the build directory
         let test_build_dir = &self.config.build_base;
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 14931baaadf..8c788c915fe 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -3,6 +3,8 @@ use std::num::NonZeroU64;
 
 use log::trace;
 
+use rustc_const_eval::ReportErrorExt;
+use rustc_errors::DiagnosticMessage;
 use rustc_span::{source_map::DUMMY_SP, SpanData, Symbol};
 use rustc_target::abi::{Align, Size};
 
@@ -83,7 +85,21 @@ impl fmt::Display for TerminationInfo {
     }
 }
 
-impl MachineStopType for TerminationInfo {}
+impl fmt::Debug for TerminationInfo {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{self}")
+    }
+}
+
+impl MachineStopType for TerminationInfo {
+    fn diagnostic_message(&self) -> DiagnosticMessage {
+        self.to_string().into()
+    }
+    fn add_args(
+        self: Box<Self>,
+        _: &mut dyn FnMut(std::borrow::Cow<'static, str>, rustc_errors::DiagnosticArgValue<'static>),
+    ) {}
+}
 
 /// Miri specific diagnostics
 pub enum NonHaltingDiagnostic {
@@ -302,8 +318,32 @@ pub fn report_error<'tcx, 'mir>(
 
     let stacktrace = ecx.generate_stacktrace();
     let (stacktrace, was_pruned) = prune_stacktrace(stacktrace, &ecx.machine);
-    e.print_backtrace();
-    msg.insert(0, e.to_string());
+    let (e, backtrace) = e.into_parts();
+    backtrace.print_backtrace();
+
+    // We want to dump the allocation if this is `InvalidUninitBytes`. Since `add_args` consumes
+    // the `InterpError`, we extract the variables it before that.
+    let extra = match e {
+        UndefinedBehavior(UndefinedBehaviorInfo::InvalidUninitBytes(Some((alloc_id, access)))) => {
+            Some((alloc_id, access))
+        }
+        _ => None
+    };
+
+    // FIXME(fee1-dead), HACK: we want to use the error as title therefore we can just extract the
+    // label and arguments from the InterpError.
+    let e = {
+        let handler = &ecx.tcx.sess.parse_sess.span_diagnostic;
+        let mut diag = ecx.tcx.sess.struct_allow("");
+        let msg = e.diagnostic_message();
+        e.add_args(handler, &mut diag);
+        let s = handler.eagerly_translate_to_string(msg, diag.args());
+        diag.cancel();
+        s
+    };
+
+    msg.insert(0, e);
+
     report_msg(
         DiagLevel::Error,
         if let Some(title) = title { format!("{title}: {}", msg[0]) } else { msg[0].clone() },
@@ -332,15 +372,12 @@ pub fn report_error<'tcx, 'mir>(
     }
 
     // Extra output to help debug specific issues.
-    match e.kind() {
-        UndefinedBehavior(UndefinedBehaviorInfo::InvalidUninitBytes(Some((alloc_id, access)))) => {
-            eprintln!(
-                "Uninitialized memory occurred at {alloc_id:?}{range:?}, in this allocation:",
-                range = access.uninit,
-            );
-            eprintln!("{:?}", ecx.dump_alloc(*alloc_id));
-        }
-        _ => {}
+    if let Some((alloc_id, access)) = extra {
+        eprintln!(
+            "Uninitialized memory occurred at {alloc_id:?}{range:?}, in this allocation:",
+            range = access.uninit,
+        );
+        eprintln!("{:?}", ecx.dump_alloc(alloc_id));
     }
 
     None
@@ -438,12 +475,15 @@ pub fn report_msg<'tcx>(
         // Add visual separator before backtrace.
         err.note(if extra_span { "BACKTRACE (of the first span):" } else { "BACKTRACE:" });
     }
+
+    let (mut err, handler) = err.into_diagnostic().unwrap();
+    
     // Add backtrace
     for (idx, frame_info) in stacktrace.iter().enumerate() {
         let is_local = machine.is_local(frame_info);
         // No span for non-local frames and the first frame (which is the error site).
         if is_local && idx > 0 {
-            err.span_note(frame_info.span, frame_info.to_string());
+            err.eager_subdiagnostic(handler, frame_info.as_note(machine.tcx));
         } else {
             let sm = sess.source_map();
             let span = sm.span_to_embeddable_string(frame_info.span);
@@ -451,7 +491,7 @@ pub fn report_msg<'tcx>(
         }
     }
 
-    err.emit();
+    handler.emit_diagnostic(&mut err);
 }
 
 impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs
index 43d8f221ce3..1e9d48be65e 100644
--- a/src/tools/miri/src/eval.rs
+++ b/src/tools/miri/src/eval.rs
@@ -422,8 +422,9 @@ pub fn eval_entry<'tcx>(
     let mut ecx = match create_ecx(tcx, entry_id, entry_type, &config) {
         Ok(v) => v,
         Err(err) => {
-            err.print_backtrace();
-            panic!("Miri initialization error: {}", err.kind())
+            let (kind, backtrace) = err.into_parts();
+            backtrace.print_backtrace();
+            panic!("Miri initialization error: {kind:?}")
         }
     };
 
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index a2b49e6f219..f1190265239 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -164,9 +164,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         // We don't give a span -- this isn't actually used directly by the program anyway.
         let const_val = this
             .eval_global(cid, None)
-            .unwrap_or_else(|err| panic!("failed to evaluate required Rust item: {path:?}\n{err}"));
+            .unwrap_or_else(|err| panic!("failed to evaluate required Rust item: {path:?}\n{err:?}"));
         this.read_scalar(&const_val.into())
-            .unwrap_or_else(|err| panic!("failed to read required Rust item: {path:?}\n{err}"))
+            .unwrap_or_else(|err| panic!("failed to read required Rust item: {path:?}\n{err:?}"))
     }
 
     /// Helper function to get a `libc` constant as a `Scalar`.
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 893a4dbd4c8..f711f01f323 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -43,6 +43,7 @@
 
 extern crate rustc_apfloat;
 extern crate rustc_ast;
+extern crate rustc_errors;
 #[macro_use]
 extern crate rustc_middle;
 extern crate rustc_const_eval;
diff --git a/src/tools/miri/tests/fail/intrinsics/copy_overlapping.rs b/src/tools/miri/tests/fail/intrinsics/copy_overlapping.rs
index 3df881bd43c..9c73bdc17be 100644
--- a/src/tools/miri/tests/fail/intrinsics/copy_overlapping.rs
+++ b/src/tools/miri/tests/fail/intrinsics/copy_overlapping.rs
@@ -10,6 +10,6 @@ fn main() {
     unsafe {
         let a = data.as_mut_ptr();
         let b = a.wrapping_offset(1) as *mut _;
-        copy_nonoverlapping(a, b, 2); //~ ERROR: copy_nonoverlapping called on overlapping ranges
+        copy_nonoverlapping(a, b, 2); //~ ERROR: `copy_nonoverlapping` called on overlapping ranges
     }
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/copy_overlapping.stderr b/src/tools/miri/tests/fail/intrinsics/copy_overlapping.stderr
index cdb3da74ca9..13a76aae730 100644
--- a/src/tools/miri/tests/fail/intrinsics/copy_overlapping.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/copy_overlapping.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: copy_nonoverlapping called on overlapping ranges
+error: Undefined Behavior: `copy_nonoverlapping` called on overlapping ranges
   --> $DIR/copy_overlapping.rs:LL:CC
    |
 LL |         copy_nonoverlapping(a, b, 2);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ copy_nonoverlapping called on overlapping ranges
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `copy_nonoverlapping` called on overlapping ranges
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_oob.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_oob.stderr
index a31b929d7a7..0b9cda62b33 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_oob.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_from_oob.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: out-of-bounds offset_from: ALLOC has size 4, so pointer at offset 10 is out-of-bounds
+error: Undefined Behavior: out-of-bounds `offset_from`: ALLOC has size 4, so pointer at offset 10 is out-of-bounds
   --> $DIR/ptr_offset_from_oob.rs:LL:CC
    |
 LL |     unsafe { end_ptr.offset_from(end_ptr) };
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: ALLOC has size 4, so pointer at offset 10 is out-of-bounds
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: ALLOC has size 4, so pointer at offset 10 is out-of-bounds
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/modifying_constants.rs b/src/tools/miri/tests/fail/modifying_constants.rs
index 2783ebd155f..40ba31dad8f 100644
--- a/src/tools/miri/tests/fail/modifying_constants.rs
+++ b/src/tools/miri/tests/fail/modifying_constants.rs
@@ -1,6 +1,8 @@
 // This should fail even without validation/SB
 //@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows
 
+#![allow(cast_ref_to_mut)]
+
 fn main() {
     let x = &1; // the `&1` is promoted to a constant, but it used to be that only the pointer is marked static, not the pointee
     let y = unsafe { &mut *(x as *const i32 as *mut i32) };
diff --git a/src/tools/miri/tests/fail/stacked_borrows/shr_frozen_violation1.rs b/src/tools/miri/tests/fail/stacked_borrows/shr_frozen_violation1.rs
index d1322dc6e57..8cd59b3550d 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/shr_frozen_violation1.rs
+++ b/src/tools/miri/tests/fail/stacked_borrows/shr_frozen_violation1.rs
@@ -1,3 +1,5 @@
+#![allow(cast_ref_to_mut)]
+
 fn foo(x: &mut i32) -> i32 {
     *x = 5;
     unknown_code(&*x);
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/builtin_attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/builtin_attr.rs
index f7c1e683d0d..142b1229019 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/builtin_attr.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/builtin_attr.rs
@@ -196,10 +196,6 @@ pub const INERT_ATTRIBUTES: &[BuiltinAttribute] = &[
     ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing),
     ungated!(type_length_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing),
     gated!(
-        const_eval_limit, CrateLevel, template!(NameValueStr: "N"), ErrorFollowing,
-        const_eval_limit, experimental!(const_eval_limit)
-    ),
-    gated!(
         move_size_limit, CrateLevel, template!(NameValueStr: "N"), ErrorFollowing,
         large_assignments, experimental!(move_size_limit)
     ),
diff --git a/src/tools/rust-installer/combine-installers.sh b/src/tools/rust-installer/combine-installers.sh
index bee5319fd55..01e5a00af4a 100755
--- a/src/tools/rust-installer/combine-installers.sh
+++ b/src/tools/rust-installer/combine-installers.sh
@@ -11,5 +11,9 @@ abs_path() {
     (unset CDPATH && cd "$path" > /dev/null && pwd)
 }
 
+# Running cargo will read the libstd Cargo.toml
+# which uses the unstable `public-dependency` feature.
+export RUSTC_BOOTSTRAP=1
+
 src_dir="$(abs_path $(dirname "$0"))"
 $CARGO run --manifest-path="$src_dir/Cargo.toml" -- combine "$@"
diff --git a/src/tools/rust-installer/gen-installer.sh b/src/tools/rust-installer/gen-installer.sh
index eabd8c95cd8..cc45b5e0803 100755
--- a/src/tools/rust-installer/gen-installer.sh
+++ b/src/tools/rust-installer/gen-installer.sh
@@ -11,5 +11,9 @@ abs_path() {
     (unset CDPATH && cd "$path" > /dev/null && pwd)
 }
 
+# Running cargo will read the libstd Cargo.toml
+# which uses the unstable `public-dependency` feature.
+export RUSTC_BOOTSTRAP=1
+
 src_dir="$(abs_path $(dirname "$0"))"
 $CARGO run --manifest-path="$src_dir/Cargo.toml" -- generate "$@"
diff --git a/src/tools/rust-installer/make-tarballs.sh b/src/tools/rust-installer/make-tarballs.sh
index e342007da37..374e103e89c 100755
--- a/src/tools/rust-installer/make-tarballs.sh
+++ b/src/tools/rust-installer/make-tarballs.sh
@@ -11,5 +11,9 @@ abs_path() {
     (unset CDPATH && cd "$path" > /dev/null && pwd)
 }
 
+# Running cargo will read the libstd Cargo.toml
+# which uses the unstable `public-dependency` feature.
+export RUSTC_BOOTSTRAP=1
+
 src_dir="$(abs_path $(dirname "$0"))"
 $CARGO run --manifest-path="$src_dir/Cargo.toml" -- tarball "$@"
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index 1c4d96c321c..e21068490b6 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -16,6 +16,12 @@ use std::sync::atomic::{AtomicBool, Ordering};
 use std::thread::{self, scope, ScopedJoinHandle};
 
 fn main() {
+    // Running Cargo will read the libstd Cargo.toml
+    // which uses the unstable `public-dependency` feature.
+    //
+    // `setenv` might not be thread safe, so run it before using multiple threads.
+    env::set_var("RUSTC_BOOTSTRAP", "1");
+
     let root_path: PathBuf = env::args_os().nth(1).expect("need path to root of repo").into();
     let cargo: PathBuf = env::args_os().nth(2).expect("need path to cargo").into();
     let output_directory: PathBuf =
diff --git a/tests/assembly/asm/mips-types.rs b/tests/assembly/asm/mips-types.rs
index 6aa28b062db..27469b22980 100644
--- a/tests/assembly/asm/mips-types.rs
+++ b/tests/assembly/asm/mips-types.rs
@@ -72,7 +72,7 @@ macro_rules! check_reg { ($func:ident, $ty:ty, $reg:tt, $mov:literal) => {
 
 // mips32-LABEL: sym_static_32:
 // mips32: #APP
-// mips32: lw $3, %got(extern_static)
+// mips32: lw $3, %got(extern_static)($gp)
 // mips32: #NO_APP
 #[cfg(mips32)]
 #[no_mangle]
@@ -82,7 +82,7 @@ pub unsafe fn sym_static_32() {
 
 // mips32-LABEL: sym_fn_32:
 // mips32: #APP
-// mips32: lw $3, %got(extern_func)
+// mips32: lw $3, %got(extern_func)($gp)
 // mips32: #NO_APP
 #[cfg(mips32)]
 #[no_mangle]
@@ -92,7 +92,9 @@ pub unsafe fn sym_fn_32() {
 
 // mips64-LABEL: sym_static_64:
 // mips64: #APP
-// mips64: ld $3, %got_disp(extern_static)
+// mips64: lui    $3, %got_hi(extern_static)
+// mips64: daddu  $3, $3, $gp
+// mips64: ld     $3, %got_lo(extern_static)($3)
 // mips64: #NO_APP
 #[cfg(mips64)]
 #[no_mangle]
@@ -102,7 +104,9 @@ pub unsafe fn sym_static_64() {
 
 // mips64-LABEL: sym_fn_64:
 // mips64: #APP
-// mips64: ld $3, %got_disp(extern_func)
+// mips64: lui    $3, %got_hi(extern_func)
+// mips64: daddu  $3, $3, $gp
+// mips64: ld     $3, %got_lo(extern_func)($3)
 // mips64: #NO_APP
 #[cfg(mips64)]
 #[no_mangle]
diff --git a/tests/codegen/const_scalar_pair.rs b/tests/codegen/const_scalar_pair.rs
index 8f32c50b798..aa4cf7a64d5 100644
--- a/tests/codegen/const_scalar_pair.rs
+++ b/tests/codegen/const_scalar_pair.rs
@@ -2,6 +2,8 @@
 
 #![feature(inline_const)]
 
+// Test that we don't generate a memory allocation for the constant
+// and read the fields from that, but instead just create the value pair directly.
 pub fn foo() -> (i32, i32) {
     // CHECK: ret { i32, i32 } { i32 1, i32 2 }
     const { (1, 2) }
diff --git a/tests/codegen/intrinsics/transmute.rs b/tests/codegen/intrinsics/transmute.rs
index 664e697c2a5..fe42494000e 100644
--- a/tests/codegen/intrinsics/transmute.rs
+++ b/tests/codegen/intrinsics/transmute.rs
@@ -14,10 +14,10 @@ use std::intrinsics::{transmute, transmute_unchecked};
 // Some of these need custom MIR to not get removed by MIR optimizations.
 use std::intrinsics::mir::*;
 
-enum Never {}
+pub enum ZstNever {}
 
 #[repr(align(2))]
-pub struct BigNever(Never, u16, Never);
+pub struct BigNever(ZstNever, u16, ZstNever);
 
 #[repr(align(8))]
 pub struct Scalar64(i64);
@@ -56,11 +56,13 @@ pub unsafe fn check_bigger_array(x: [u32; 3]) -> [u32; 7] {
     transmute_unchecked(x)
 }
 
-// CHECK-LABEL: @check_to_uninhabited(
+// CHECK-LABEL: @check_to_empty_array(
 #[no_mangle]
 #[custom_mir(dialect = "runtime", phase = "optimized")]
-pub unsafe fn check_to_uninhabited(x: u16) -> BigNever {
+pub unsafe fn check_to_empty_array(x: [u32; 5]) -> [u32; 0] {
+    // CHECK-NOT: trap
     // CHECK: call void @llvm.trap
+    // CHECK-NOT: trap
     mir!{
         {
             RET = CastTransmute(x);
@@ -69,6 +71,37 @@ pub unsafe fn check_to_uninhabited(x: u16) -> BigNever {
     }
 }
 
+// CHECK-LABEL: @check_from_empty_array(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+pub unsafe fn check_from_empty_array(x: [u32; 0]) -> [u32; 5] {
+    // CHECK-NOT: trap
+    // CHECK: call void @llvm.trap
+    // CHECK-NOT: trap
+    mir!{
+        {
+            RET = CastTransmute(x);
+            Return()
+        }
+    }
+}
+
+// CHECK-LABEL: @check_to_uninhabited(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+pub unsafe fn check_to_uninhabited(x: u16) {
+    // CHECK-NOT: trap
+    // CHECK: call void @llvm.trap
+    // CHECK-NOT: trap
+    mir!{
+        let temp: BigNever;
+        {
+            temp = CastTransmute(x);
+            Return()
+        }
+    }
+}
+
 // CHECK-LABEL: @check_from_uninhabited(
 #[no_mangle]
 #[custom_mir(dialect = "runtime", phase = "optimized")]
@@ -366,6 +399,40 @@ pub unsafe fn check_issue_109992(x: ()) -> [(); 1] {
     }
 }
 
+// CHECK-LABEL: @check_unit_to_never(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+pub unsafe fn check_unit_to_never(x: ()) {
+    // This uses custom MIR to avoid MIR optimizations having removed ZST ops.
+
+    // CHECK-NOT: trap
+    // CHECK: call void @llvm.trap
+    // CHECK-NOT: trap
+    mir!{
+        let temp: ZstNever;
+        {
+            temp = CastTransmute(x);
+            Return()
+        }
+    }
+}
+
+// CHECK-LABEL: @check_unit_from_never(
+#[no_mangle]
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+pub unsafe fn check_unit_from_never(x: ZstNever) -> () {
+    // This uses custom MIR to avoid MIR optimizations having removed ZST ops.
+
+    // CHECK: start
+    // CHECK-NEXT: ret void
+    mir!{
+        {
+            RET = CastTransmute(x);
+            Return()
+        }
+    }
+}
+
 // CHECK-LABEL: @check_maybe_uninit_pair(i16 %x.0, i64 %x.1)
 #[no_mangle]
 pub unsafe fn check_maybe_uninit_pair(
diff --git a/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs
index 2ee4d7cca0e..6e0eacfe400 100644
--- a/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs
+++ b/tests/codegen/issues/issue-105386-ub-in-debuginfo.rs
@@ -1,4 +1,5 @@
-// compile-flags: --crate-type=lib -O -Cdebuginfo=2 -Cno-prepopulate-passes
+// compile-flags: --crate-type=lib -O -Cdebuginfo=2 -Cno-prepopulate-passes -Zmir-enable-passes=-ScalarReplacementOfAggregates
+// MIR SROA will decompose the closure
 // min-llvm-version: 15.0 # this test uses opaque pointer notation
 #![feature(stmt_expr_attributes)]
 
@@ -15,8 +16,8 @@ pub fn outer_function(x: S, y: S) -> usize {
 // Check that we do not attempt to load from the spilled arg before it is assigned to
 // when generating debuginfo.
 // CHECK-LABEL: @outer_function
-// CHECK: [[spill:%.*]] = alloca %"[closure@{{.*.rs}}:9:23: 9:25]"
-// CHECK-NOT: [[ptr_tmp:%.*]] = getelementptr inbounds %"[closure@{{.*.rs}}:9:23: 9:25]", ptr [[spill]]
+// CHECK: [[spill:%.*]] = alloca %"[closure@{{.*.rs}}:10:23: 10:25]"
+// CHECK-NOT: [[ptr_tmp:%.*]] = getelementptr inbounds %"[closure@{{.*.rs}}:10:23: 10:25]", ptr [[spill]]
 // CHECK-NOT: [[load:%.*]] = load ptr, ptr
 // CHECK: call void @llvm.lifetime.start{{.*}}({{.*}}, ptr [[spill]])
 // CHECK: [[inner:%.*]] = getelementptr inbounds %"{{.*}}", ptr [[spill]]
diff --git a/tests/incremental/hashes/match_expressions.rs b/tests/incremental/hashes/match_expressions.rs
index 4429df6833e..ecb19480d65 100644
--- a/tests/incremental/hashes/match_expressions.rs
+++ b/tests/incremental/hashes/match_expressions.rs
@@ -225,8 +225,9 @@ pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 {
     }
 }
 
+// Ignore optimized_mir in cfail2, the only change to optimized MIR is a span.
 #[cfg(not(any(cfail1,cfail4)))]
-#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
+#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
 #[rustc_clean(cfg="cfail3")]
 #[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
 #[rustc_clean(cfg="cfail6")]
diff --git a/tests/incremental/issue-101518.rs b/tests/incremental/issue-101518.rs
index 501be175fce..39373da6a9f 100644
--- a/tests/incremental/issue-101518.rs
+++ b/tests/incremental/issue-101518.rs
@@ -1,7 +1,4 @@
-// revisions: cfail1
-// should-ice
-// error-pattern: forcing query
-// known-bug: #101518
+// revisions: cpass
 
 #[derive(PartialEq, Eq)]
 struct Id<'a> {
@@ -9,9 +6,7 @@ struct Id<'a> {
 }
 fn visit_struct() {
     let id = Id { ns: "random1" };
-    const FLAG: Id<'static> = Id {
-        ns: "needs_to_be_the_same",
-    };
+    const FLAG: Id<'static> = Id { ns: "needs_to_be_the_same" };
     match id {
         FLAG => {}
         _ => {}
@@ -19,9 +14,7 @@ fn visit_struct() {
 }
 fn visit_struct2() {
     let id = Id { ns: "random2" };
-    const FLAG: Id<'static> = Id {
-        ns: "needs_to_be_the_same",
-    };
+    const FLAG: Id<'static> = Id { ns: "needs_to_be_the_same" };
     match id {
         FLAG => {}
         _ => {}
diff --git a/tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir b/tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir
index bcdb12011bc..61ce5e54fdc 100644
--- a/tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir
+++ b/tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir
@@ -35,7 +35,7 @@ fn foo(_1: Option<String>) -> i32 {
                                          // + literal: Const { ty: for<'a, 'b> fn(&'a str, &'b str) -> bool {<str as PartialEq>::eq}, val: Value(<ZST>) }
                                          // mir::Constant
                                          // + span: $DIR/string.rs:9:14: 9:17
-                                         // + literal: Const { ty: &str, val: Value(Slice(..)) }
+                                         // + literal: Const { ty: &str, val: Value(ValTree::Branch(..)) }
     }
 
     bb3: {
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
index d76cd0e2bb8..e82e3f18811 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff
@@ -11,35 +11,33 @@
 +         debug self => _3;                // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +         debug rhs => _4;                 // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +         let mut _5: u16;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         let mut _6: (u32,);              // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         let mut _7: u32;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         scope 2 {
 +             scope 3 (inlined core::num::<impl u16>::unchecked_shl::conv) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+                 debug x => _7;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+                 let mut _8: std::option::Option<u16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+                 let mut _9: std::result::Result<u16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 debug x => _4;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 let mut _6: std::option::Option<u16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 let mut _7: std::result::Result<u16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +                 scope 4 {
 +                     scope 5 (inlined <u32 as TryInto<u16>>::try_into) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+                         debug self => _7; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
++                         debug self => _4; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
 +                         scope 6 (inlined convert::num::<impl TryFrom<u32> for u16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
-+                             debug u => _7; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+                             let mut _10: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+                             let mut _11: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+                             let mut _12: u16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             debug u => _4; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _8: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _9: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _10: u16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
 +                         }
 +                     }
 +                     scope 7 (inlined Result::<u16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+                         debug self => _9; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-+                         let mut _13: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-+                         let _14: u16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         debug self => _7; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         let mut _11: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         let _12: u16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
 +                         scope 8 {
-+                             debug x => _14; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
++                             debug x => _12; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
 +                         }
 +                     }
 +                     scope 9 (inlined #[track_caller] Option::<u16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+                         debug self => _8; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-+                         let mut _15: &std::option::Option<u16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-+                         let mut _16: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         debug self => _6; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         let mut _13: &std::option::Option<u16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         let mut _14: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
 +                         scope 10 {
 +                             debug val => _5; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
 +                         }
@@ -52,7 +50,7 @@
 +                             }
 +                         }
 +                         scope 12 (inlined Option::<u16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
-+                             debug self => _15; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
++                             debug self => _13; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
 +                         }
 +                     }
 +                 }
@@ -70,18 +68,14 @@
 -                                          // + span: $DIR/unchecked_shifts.rs:11:7: 11:20
 -                                          // + literal: Const { ty: unsafe fn(u16, u32) -> u16 {core::num::<impl u16>::unchecked_shl}, val: Value(<ZST>) }
 +         StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         StorageLive(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         _6 = (_4,);                      // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         StorageLive(_7);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         _7 = move (_6.0: u32);           // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         StorageLive(_9);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+         StorageLive(_11);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+         _11 = const 65535_u32;           // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+         _10 = Gt(_7, move _11);          // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+         StorageDead(_11);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+         switchInt(move _10) -> [0: bb3, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_7);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_8);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_9);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _9 = const 65535_u32;            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _8 = Gt(_4, move _9);            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_9);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         switchInt(move _8) -> [0: bb3, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
       }
   
       bb1: {
@@ -92,7 +86,7 @@
 +     }
 + 
 +     bb2: {
-+         _9 = Result::<u16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _7 = Result::<u16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
 +                                          // mir::Constant
 +                                          // + span: no-location
 +                                          // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
@@ -100,22 +94,22 @@
 +     }
 + 
 +     bb3: {
-+         StorageLive(_12);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+         _12 = _7 as u16 (IntToInt);      // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+         _9 = Result::<u16, TryFromIntError>::Ok(move _12); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+         StorageDead(_12);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _10 = _4 as u16 (IntToInt);      // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _7 = Result::<u16, TryFromIntError>::Ok(move _10); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
 +         goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
 +     }
 + 
 +     bb4: {
-+         StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+         StorageLive(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         _13 = discriminant(_9);          // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-+         switchInt(move _13) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         StorageDead(_8);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _11 = discriminant(_7);          // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         switchInt(move _11) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
 +     }
 + 
 +     bb5: {
-+         _8 = Option::<u16>::None;        // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         _6 = Option::<u16>::None;        // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
 +         goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
 +     }
 + 
@@ -124,25 +118,23 @@
 +     }
 + 
 +     bb7: {
-+         _14 = move ((_9 as Ok).0: u16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-+         _8 = Option::<u16>::Some(move _14); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
++         _12 = move ((_7 as Ok).0: u16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         _6 = Option::<u16>::Some(move _12); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
 +         goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
 +     }
 + 
 +     bb8: {
-+         StorageDead(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         StorageLive(_15);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         _16 = discriminant(_8);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-+         switchInt(move _16) -> [1: bb9, otherwise: bb6]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         StorageDead(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_7);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_13);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _14 = discriminant(_6);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         switchInt(move _14) -> [1: bb9, otherwise: bb6]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
 +     }
 + 
 +     bb9: {
-+         _5 = move ((_8 as Some).0: u16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-+         StorageDead(_15);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         StorageDead(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         StorageDead(_7);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _5 = move ((_6 as Some).0: u16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         StorageDead(_13);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         _0 = unchecked_shl::<u16>(_3, move _5) -> [return: bb1, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +                                          // mir::Constant
 +                                          // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
index f4b2416eaab..8fa4fdaa49a 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir
@@ -7,38 +7,36 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
     scope 1 (inlined core::num::<impl u16>::unchecked_shl) { // at $DIR/unchecked_shifts.rs:11:7: 11:23
         debug self => _1;                // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
         debug rhs => _2;                 // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-        let mut _3: (u32,);              // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        let mut _4: u32;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        let mut _13: u16;                // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        let mut _11: u16;                // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         scope 2 {
             scope 3 (inlined core::num::<impl u16>::unchecked_shl::conv) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                debug x => _4;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                let mut _8: std::result::Result<u16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                let mut _11: std::option::Option<u16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                debug x => _2;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                let mut _6: std::result::Result<u16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                let mut _9: std::option::Option<u16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
                 scope 4 {
                     scope 5 (inlined <u32 as TryInto<u16>>::try_into) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                        debug self => _4; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                        debug self => _2; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
                         scope 6 (inlined convert::num::<impl TryFrom<u32> for u16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
-                            debug u => _4; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-                            let mut _5: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-                            let mut _6: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-                            let mut _7: u16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            debug u => _2; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _3: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _4: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _5: u16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
                         }
                     }
                     scope 7 (inlined Result::<u16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                        debug self => _8; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-                        let mut _9: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-                        let _10: u16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        debug self => _6; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        let mut _7: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        let _8: u16;     // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
                         scope 8 {
-                            debug x => _10; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+                            debug x => _8; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
                         }
                     }
                     scope 9 (inlined #[track_caller] Option::<u16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                        debug self => _11; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-                        let mut _12: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-                        let mut _14: &std::option::Option<u16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        debug self => _9; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        let mut _10: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        let mut _12: &std::option::Option<u16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
                         scope 10 {
-                            debug val => _13; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
+                            debug val => _11; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
                         }
                         scope 11 {
                             scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
@@ -49,7 +47,7 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
                             }
                         }
                         scope 12 (inlined Option::<u16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
-                            debug self => _14; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
+                            debug self => _12; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
                         }
                     }
                 }
@@ -58,31 +56,27 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
     }
 
     bb0: {
-        StorageLive(_13);                // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _3 = (_2,);                      // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _4 = move (_3.0: u32);           // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_11);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_6);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        StorageLive(_5);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        _5 = const 65535_u32;            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        _6 = Gt(_4, move _5);            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        StorageDead(_5);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        switchInt(move _6) -> [0: bb1, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_11);                // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_9);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_4);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_3);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _3 = const 65535_u32;            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _4 = Gt(_2, move _3);            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_3);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        switchInt(move _4) -> [0: bb1, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb1: {
-        StorageLive(_7);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        _7 = _4 as u16 (IntToInt);       // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        _8 = Result::<u16, TryFromIntError>::Ok(move _7); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        StorageDead(_7);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_5);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _5 = _2 as u16 (IntToInt);       // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _6 = Result::<u16, TryFromIntError>::Ok(move _5); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_5);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
         goto -> bb3;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb2: {
-        _8 = Result::<u16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _6 = Result::<u16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
                                          // mir::Constant
                                          // + span: no-location
                                          // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
@@ -90,45 +84,43 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
     }
 
     bb3: {
-        StorageDead(_6);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        StorageLive(_10);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _9 = discriminant(_8);           // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-        switchInt(move _9) -> [0: bb4, 1: bb5, otherwise: bb9]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        StorageDead(_4);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _7 = discriminant(_6);           // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        switchInt(move _7) -> [0: bb4, 1: bb5, otherwise: bb9]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb4: {
-        _10 = move ((_8 as Ok).0: u16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-        _11 = Option::<u16>::Some(move _10); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+        _8 = move ((_6 as Ok).0: u16);   // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        _9 = Option::<u16>::Some(move _8); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
         goto -> bb6;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb5: {
-        _11 = Option::<u16>::None;       // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        _9 = Option::<u16>::None;        // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
         goto -> bb6;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb6: {
-        StorageDead(_10);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         StorageDead(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _12 = discriminant(_11);         // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-        switchInt(move _12) -> [1: bb7, otherwise: bb9]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _10 = discriminant(_9);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        switchInt(move _10) -> [1: bb7, otherwise: bb9]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
     }
 
     bb7: {
-        _13 = move ((_11 as Some).0: u16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-        StorageDead(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageDead(_11);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _0 = unchecked_shl::<u16>(_1, move _13) -> [return: bb8, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        _11 = move ((_9 as Some).0: u16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _0 = unchecked_shl::<u16>(_1, move _11) -> [return: bb8, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u16, u16) -> u16 {unchecked_shl::<u16>}, val: Value(<ZST>) }
     }
 
     bb8: {
-        StorageDead(_13);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        StorageDead(_11);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
         return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
     }
 
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
index f3d3e6090bb..f20c7da4747 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff
@@ -11,35 +11,33 @@
 +         debug self => _3;                // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +         debug rhs => _4;                 // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +         let mut _5: i16;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         let mut _6: (u32,);              // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         let mut _7: u32;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         scope 2 {
 +             scope 3 (inlined core::num::<impl i16>::unchecked_shr::conv) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+                 debug x => _7;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+                 let mut _8: std::option::Option<i16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+                 let mut _9: std::result::Result<i16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 debug x => _4;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 let mut _6: std::option::Option<i16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++                 let mut _7: std::result::Result<i16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +                 scope 4 {
 +                     scope 5 (inlined <u32 as TryInto<i16>>::try_into) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+                         debug self => _7; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
++                         debug self => _4; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
 +                         scope 6 (inlined convert::num::<impl TryFrom<u32> for i16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
-+                             debug u => _7; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+                             let mut _10: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+                             let mut _11: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+                             let mut _12: i16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             debug u => _4; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _8: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _9: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                             let mut _10: i16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
 +                         }
 +                     }
 +                     scope 7 (inlined Result::<i16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+                         debug self => _9; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-+                         let mut _13: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-+                         let _14: i16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         debug self => _7; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         let mut _11: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++                         let _12: i16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
 +                         scope 8 {
-+                             debug x => _14; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
++                             debug x => _12; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
 +                         }
 +                     }
 +                     scope 9 (inlined #[track_caller] Option::<i16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+                         debug self => _8; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-+                         let mut _15: &std::option::Option<i16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-+                         let mut _16: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         debug self => _6; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         let mut _13: &std::option::Option<i16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++                         let mut _14: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
 +                         scope 10 {
 +                             debug val => _5; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
 +                         }
@@ -52,7 +50,7 @@
 +                             }
 +                         }
 +                         scope 12 (inlined Option::<i16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
-+                             debug self => _15; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
++                             debug self => _13; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
 +                         }
 +                     }
 +                 }
@@ -70,18 +68,14 @@
 -                                          // + span: $DIR/unchecked_shifts.rs:17:7: 17:20
 -                                          // + literal: Const { ty: unsafe fn(i16, u32) -> i16 {core::num::<impl i16>::unchecked_shr}, val: Value(<ZST>) }
 +         StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         StorageLive(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         _6 = (_4,);                      // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         StorageLive(_7);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         _7 = move (_6.0: u32);           // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         StorageLive(_9);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+         StorageLive(_11);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+         _11 = const 32767_u32;           // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+         _10 = Gt(_7, move _11);          // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+         StorageDead(_11);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+         switchInt(move _10) -> [0: bb3, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_7);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_8);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_9);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _9 = const 32767_u32;            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _8 = Gt(_4, move _9);            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_9);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         switchInt(move _8) -> [0: bb3, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
       }
   
       bb1: {
@@ -92,7 +86,7 @@
 +     }
 + 
 +     bb2: {
-+         _9 = Result::<i16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _7 = Result::<i16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
 +                                          // mir::Constant
 +                                          // + span: no-location
 +                                          // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
@@ -100,22 +94,22 @@
 +     }
 + 
 +     bb3: {
-+         StorageLive(_12);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+         _12 = _7 as i16 (IntToInt);      // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+         _9 = Result::<i16, TryFromIntError>::Ok(move _12); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+         StorageDead(_12);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _10 = _4 as i16 (IntToInt);      // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _7 = Result::<i16, TryFromIntError>::Ok(move _10); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
 +         goto -> bb4;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
 +     }
 + 
 +     bb4: {
-+         StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-+         StorageLive(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         _13 = discriminant(_9);          // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-+         switchInt(move _13) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         StorageDead(_8);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _11 = discriminant(_7);          // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         switchInt(move _11) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
 +     }
 + 
 +     bb5: {
-+         _8 = Option::<i16>::None;        // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         _6 = Option::<i16>::None;        // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
 +         goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
 +     }
 + 
@@ -124,25 +118,23 @@
 +     }
 + 
 +     bb7: {
-+         _14 = move ((_9 as Ok).0: i16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-+         _8 = Option::<i16>::Some(move _14); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
++         _12 = move ((_7 as Ok).0: i16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
++         _6 = Option::<i16>::Some(move _12); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
 +         goto -> bb8;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
 +     }
 + 
 +     bb8: {
-+         StorageDead(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         StorageLive(_15);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         _16 = discriminant(_8);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-+         switchInt(move _16) -> [1: bb9, otherwise: bb6]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         StorageDead(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_7);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageLive(_13);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _14 = discriminant(_6);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         switchInt(move _14) -> [1: bb9, otherwise: bb6]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
 +     }
 + 
 +     bb9: {
-+         _5 = move ((_8 as Some).0: i16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-+         StorageDead(_15);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         StorageDead(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         StorageDead(_7);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-+         StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         _5 = move ((_6 as Some).0: i16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         StorageDead(_13);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
++         StorageDead(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
 +         _0 = unchecked_shr::<i16>(_3, move _5) -> [return: bb1, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +                                          // mir::Constant
 +                                          // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
diff --git a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
index 67f0fe8932f..7f737abb936 100644
--- a/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
+++ b/tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir
@@ -7,38 +7,36 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
     scope 1 (inlined core::num::<impl i16>::unchecked_shr) { // at $DIR/unchecked_shifts.rs:17:7: 17:23
         debug self => _1;                // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
         debug rhs => _2;                 // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-        let mut _3: (u32,);              // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        let mut _4: u32;                 // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        let mut _13: i16;                // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        let mut _11: i16;                // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         scope 2 {
             scope 3 (inlined core::num::<impl i16>::unchecked_shr::conv) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                debug x => _4;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                let mut _8: std::result::Result<i16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                let mut _11: std::option::Option<i16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                debug x => _2;           // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                let mut _6: std::result::Result<i16, std::num::TryFromIntError>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                let mut _9: std::option::Option<i16>; // in scope 3 at $SRC_DIR/core/src/num/mod.rs:LL:COL
                 scope 4 {
                     scope 5 (inlined <u32 as TryInto<i16>>::try_into) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                        debug self => _4; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                        debug self => _2; // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
                         scope 6 (inlined convert::num::<impl TryFrom<u32> for i16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
-                            debug u => _4; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-                            let mut _5: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-                            let mut _6: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-                            let mut _7: i16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            debug u => _2; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _3: u32; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _4: bool; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                            let mut _5: i16; // in scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
                         }
                     }
                     scope 7 (inlined Result::<i16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                        debug self => _8; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-                        let mut _9: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-                        let _10: i16;    // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        debug self => _6; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        let mut _7: isize; // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+                        let _8: i16;     // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
                         scope 8 {
-                            debug x => _10; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+                            debug x => _8; // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
                         }
                     }
                     scope 9 (inlined #[track_caller] Option::<i16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
-                        debug self => _11; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-                        let mut _12: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-                        let mut _14: &std::option::Option<i16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        debug self => _9; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        let mut _10: isize; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                        let mut _12: &std::option::Option<i16>; // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
                         scope 10 {
-                            debug val => _13; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
+                            debug val => _11; // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
                         }
                         scope 11 {
                             scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
@@ -49,7 +47,7 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
                             }
                         }
                         scope 12 (inlined Option::<i16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
-                            debug self => _14; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
+                            debug self => _12; // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
                         }
                     }
                 }
@@ -58,31 +56,27 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
     }
 
     bb0: {
-        StorageLive(_13);                // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _3 = (_2,);                      // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _4 = move (_3.0: u32);           // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_11);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_6);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        StorageLive(_5);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        _5 = const 32767_u32;            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        _6 = Gt(_4, move _5);            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        StorageDead(_5);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        switchInt(move _6) -> [0: bb1, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_11);                // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_9);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_4);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_3);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _3 = const 32767_u32;            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _4 = Gt(_2, move _3);            // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_3);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        switchInt(move _4) -> [0: bb1, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb1: {
-        StorageLive(_7);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        _7 = _4 as i16 (IntToInt);       // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        _8 = Result::<i16, TryFromIntError>::Ok(move _7); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        StorageDead(_7);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_5);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _5 = _2 as i16 (IntToInt);       // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _6 = Result::<i16, TryFromIntError>::Ok(move _5); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_5);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
         goto -> bb3;                     // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb2: {
-        _8 = Result::<i16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _6 = Result::<i16, TryFromIntError>::Err(const TryFromIntError(())); // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
                                          // mir::Constant
                                          // + span: no-location
                                          // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
@@ -90,45 +84,43 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
     }
 
     bb3: {
-        StorageDead(_6);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
-        StorageLive(_10);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _9 = discriminant(_8);           // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-        switchInt(move _9) -> [0: bb4, 1: bb5, otherwise: bb9]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        StorageDead(_4);                 // scope 6 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _7 = discriminant(_6);           // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        switchInt(move _7) -> [0: bb4, 1: bb5, otherwise: bb9]; // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb4: {
-        _10 = move ((_8 as Ok).0: i16);  // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-        _11 = Option::<i16>::Some(move _10); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+        _8 = move ((_6 as Ok).0: i16);   // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        _9 = Option::<i16>::Some(move _8); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
         goto -> bb6;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb5: {
-        _11 = Option::<i16>::None;       // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+        _9 = Option::<i16>::None;        // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
         goto -> bb6;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb6: {
-        StorageDead(_10);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
         StorageDead(_8);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageLive(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _12 = discriminant(_11);         // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-        switchInt(move _12) -> [1: bb7, otherwise: bb9]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_6);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _10 = discriminant(_9);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        switchInt(move _10) -> [1: bb7, otherwise: bb9]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
     }
 
     bb7: {
-        _13 = move ((_11 as Some).0: i16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
-        StorageDead(_14);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageDead(_11);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
-        _0 = unchecked_shr::<i16>(_1, move _13) -> [return: bb8, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+        _11 = move ((_9 as Some).0: i16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_12);                // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _0 = unchecked_shr::<i16>(_1, move _11) -> [return: bb8, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(i16, i16) -> i16 {unchecked_shr::<i16>}, val: Value(<ZST>) }
     }
 
     bb8: {
-        StorageDead(_13);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+        StorageDead(_11);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
         return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
     }
 
diff --git a/tests/mir-opt/pre-codegen/chained_comparison.bitand.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/chained_comparison.bitand.PreCodegen.after.mir
new file mode 100644
index 00000000000..40ddf82f4cf
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/chained_comparison.bitand.PreCodegen.after.mir
@@ -0,0 +1,84 @@
+// MIR for `bitand` after PreCodegen
+
+fn bitand(_1: &Blueprint, _2: &Blueprint) -> bool {
+    debug a => _1;                       // in scope 0 at $DIR/chained_comparison.rs:+0:15: +0:16
+    debug b => _2;                       // in scope 0 at $DIR/chained_comparison.rs:+0:30: +0:31
+    let mut _0: bool;                    // return place in scope 0 at $DIR/chained_comparison.rs:+0:48: +0:52
+    let mut _3: u32;                     // in scope 0 at $DIR/chained_comparison.rs:+1:6: +1:22
+    let mut _4: u32;                     // in scope 0 at $DIR/chained_comparison.rs:+1:26: +1:42
+    let mut _5: bool;                    // in scope 0 at $DIR/chained_comparison.rs:+1:5: +1:43
+    let mut _6: u32;                     // in scope 0 at $DIR/chained_comparison.rs:+2:12: +2:21
+    let mut _7: u32;                     // in scope 0 at $DIR/chained_comparison.rs:+2:25: +2:34
+    let mut _8: bool;                    // in scope 0 at $DIR/chained_comparison.rs:+2:11: +2:35
+    let mut _9: bool;                    // in scope 0 at $DIR/chained_comparison.rs:+1:5: +2:35
+    let mut _10: u32;                    // in scope 0 at $DIR/chained_comparison.rs:+3:12: +3:28
+    let mut _11: u32;                    // in scope 0 at $DIR/chained_comparison.rs:+3:32: +3:48
+    let mut _12: bool;                   // in scope 0 at $DIR/chained_comparison.rs:+3:11: +3:49
+    let mut _13: bool;                   // in scope 0 at $DIR/chained_comparison.rs:+1:5: +3:49
+    let mut _14: u32;                    // in scope 0 at $DIR/chained_comparison.rs:+4:12: +4:25
+    let mut _15: u32;                    // in scope 0 at $DIR/chained_comparison.rs:+4:29: +4:42
+    let mut _16: bool;                   // in scope 0 at $DIR/chained_comparison.rs:+4:11: +4:43
+    let mut _17: bool;                   // in scope 0 at $DIR/chained_comparison.rs:+1:5: +4:43
+    let mut _18: u32;                    // in scope 0 at $DIR/chained_comparison.rs:+5:12: +5:21
+    let mut _19: u32;                    // in scope 0 at $DIR/chained_comparison.rs:+5:25: +5:34
+    let mut _20: bool;                   // in scope 0 at $DIR/chained_comparison.rs:+5:11: +5:35
+
+    bb0: {
+        StorageLive(_17);                // scope 0 at $DIR/chained_comparison.rs:+1:5: +4:43
+        StorageLive(_13);                // scope 0 at $DIR/chained_comparison.rs:+1:5: +3:49
+        StorageLive(_9);                 // scope 0 at $DIR/chained_comparison.rs:+1:5: +2:35
+        StorageLive(_5);                 // scope 0 at $DIR/chained_comparison.rs:+1:5: +1:43
+        StorageLive(_3);                 // scope 0 at $DIR/chained_comparison.rs:+1:6: +1:22
+        _3 = ((*_1).0: u32);             // scope 0 at $DIR/chained_comparison.rs:+1:6: +1:22
+        StorageLive(_4);                 // scope 0 at $DIR/chained_comparison.rs:+1:26: +1:42
+        _4 = ((*_2).0: u32);             // scope 0 at $DIR/chained_comparison.rs:+1:26: +1:42
+        _5 = Eq(move _3, move _4);       // scope 0 at $DIR/chained_comparison.rs:+1:5: +1:43
+        StorageDead(_4);                 // scope 0 at $DIR/chained_comparison.rs:+1:42: +1:43
+        StorageDead(_3);                 // scope 0 at $DIR/chained_comparison.rs:+1:42: +1:43
+        StorageLive(_8);                 // scope 0 at $DIR/chained_comparison.rs:+2:11: +2:35
+        StorageLive(_6);                 // scope 0 at $DIR/chained_comparison.rs:+2:12: +2:21
+        _6 = ((*_1).1: u32);             // scope 0 at $DIR/chained_comparison.rs:+2:12: +2:21
+        StorageLive(_7);                 // scope 0 at $DIR/chained_comparison.rs:+2:25: +2:34
+        _7 = ((*_2).1: u32);             // scope 0 at $DIR/chained_comparison.rs:+2:25: +2:34
+        _8 = Eq(move _6, move _7);       // scope 0 at $DIR/chained_comparison.rs:+2:11: +2:35
+        StorageDead(_7);                 // scope 0 at $DIR/chained_comparison.rs:+2:34: +2:35
+        StorageDead(_6);                 // scope 0 at $DIR/chained_comparison.rs:+2:34: +2:35
+        _9 = BitAnd(move _5, move _8);   // scope 0 at $DIR/chained_comparison.rs:+1:5: +2:35
+        StorageDead(_8);                 // scope 0 at $DIR/chained_comparison.rs:+2:34: +2:35
+        StorageDead(_5);                 // scope 0 at $DIR/chained_comparison.rs:+2:34: +2:35
+        StorageLive(_12);                // scope 0 at $DIR/chained_comparison.rs:+3:11: +3:49
+        StorageLive(_10);                // scope 0 at $DIR/chained_comparison.rs:+3:12: +3:28
+        _10 = ((*_1).2: u32);            // scope 0 at $DIR/chained_comparison.rs:+3:12: +3:28
+        StorageLive(_11);                // scope 0 at $DIR/chained_comparison.rs:+3:32: +3:48
+        _11 = ((*_2).2: u32);            // scope 0 at $DIR/chained_comparison.rs:+3:32: +3:48
+        _12 = Eq(move _10, move _11);    // scope 0 at $DIR/chained_comparison.rs:+3:11: +3:49
+        StorageDead(_11);                // scope 0 at $DIR/chained_comparison.rs:+3:48: +3:49
+        StorageDead(_10);                // scope 0 at $DIR/chained_comparison.rs:+3:48: +3:49
+        _13 = BitAnd(move _9, move _12); // scope 0 at $DIR/chained_comparison.rs:+1:5: +3:49
+        StorageDead(_12);                // scope 0 at $DIR/chained_comparison.rs:+3:48: +3:49
+        StorageDead(_9);                 // scope 0 at $DIR/chained_comparison.rs:+3:48: +3:49
+        StorageLive(_16);                // scope 0 at $DIR/chained_comparison.rs:+4:11: +4:43
+        StorageLive(_14);                // scope 0 at $DIR/chained_comparison.rs:+4:12: +4:25
+        _14 = ((*_1).3: u32);            // scope 0 at $DIR/chained_comparison.rs:+4:12: +4:25
+        StorageLive(_15);                // scope 0 at $DIR/chained_comparison.rs:+4:29: +4:42
+        _15 = ((*_2).3: u32);            // scope 0 at $DIR/chained_comparison.rs:+4:29: +4:42
+        _16 = Eq(move _14, move _15);    // scope 0 at $DIR/chained_comparison.rs:+4:11: +4:43
+        StorageDead(_15);                // scope 0 at $DIR/chained_comparison.rs:+4:42: +4:43
+        StorageDead(_14);                // scope 0 at $DIR/chained_comparison.rs:+4:42: +4:43
+        _17 = BitAnd(move _13, move _16); // scope 0 at $DIR/chained_comparison.rs:+1:5: +4:43
+        StorageDead(_16);                // scope 0 at $DIR/chained_comparison.rs:+4:42: +4:43
+        StorageDead(_13);                // scope 0 at $DIR/chained_comparison.rs:+4:42: +4:43
+        StorageLive(_20);                // scope 0 at $DIR/chained_comparison.rs:+5:11: +5:35
+        StorageLive(_18);                // scope 0 at $DIR/chained_comparison.rs:+5:12: +5:21
+        _18 = ((*_1).4: u32);            // scope 0 at $DIR/chained_comparison.rs:+5:12: +5:21
+        StorageLive(_19);                // scope 0 at $DIR/chained_comparison.rs:+5:25: +5:34
+        _19 = ((*_2).4: u32);            // scope 0 at $DIR/chained_comparison.rs:+5:25: +5:34
+        _20 = Eq(move _18, move _19);    // scope 0 at $DIR/chained_comparison.rs:+5:11: +5:35
+        StorageDead(_19);                // scope 0 at $DIR/chained_comparison.rs:+5:34: +5:35
+        StorageDead(_18);                // scope 0 at $DIR/chained_comparison.rs:+5:34: +5:35
+        _0 = BitAnd(move _17, move _20); // scope 0 at $DIR/chained_comparison.rs:+1:5: +5:35
+        StorageDead(_20);                // scope 0 at $DIR/chained_comparison.rs:+5:34: +5:35
+        StorageDead(_17);                // scope 0 at $DIR/chained_comparison.rs:+5:34: +5:35
+        return;                          // scope 0 at $DIR/chained_comparison.rs:+6:2: +6:2
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/chained_comparison.naive.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/chained_comparison.naive.PreCodegen.after.mir
new file mode 100644
index 00000000000..26ce7fda4ed
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/chained_comparison.naive.PreCodegen.after.mir
@@ -0,0 +1,127 @@
+// MIR for `naive` after PreCodegen
+
+fn naive(_1: &Blueprint, _2: &Blueprint) -> bool {
+    debug a => _1;                       // in scope 0 at $DIR/chained_comparison.rs:+0:14: +0:15
+    debug b => _2;                       // in scope 0 at $DIR/chained_comparison.rs:+0:29: +0:30
+    let mut _0: bool;                    // return place in scope 0 at $DIR/chained_comparison.rs:+0:47: +0:51
+    let mut _3: u32;                     // in scope 0 at $DIR/chained_comparison.rs:+1:6: +1:22
+    let mut _4: u32;                     // in scope 0 at $DIR/chained_comparison.rs:+1:26: +1:42
+    let mut _5: bool;                    // in scope 0 at $DIR/chained_comparison.rs:+1:5: +1:43
+    let mut _6: u32;                     // in scope 0 at $DIR/chained_comparison.rs:+2:13: +2:22
+    let mut _7: u32;                     // in scope 0 at $DIR/chained_comparison.rs:+2:26: +2:35
+    let mut _8: bool;                    // in scope 0 at $DIR/chained_comparison.rs:+2:12: +2:36
+    let mut _9: bool;                    // in scope 0 at $DIR/chained_comparison.rs:+1:5: +2:36
+    let mut _10: u32;                    // in scope 0 at $DIR/chained_comparison.rs:+3:13: +3:29
+    let mut _11: u32;                    // in scope 0 at $DIR/chained_comparison.rs:+3:33: +3:49
+    let mut _12: bool;                   // in scope 0 at $DIR/chained_comparison.rs:+3:12: +3:50
+    let mut _13: bool;                   // in scope 0 at $DIR/chained_comparison.rs:+1:5: +3:50
+    let mut _14: u32;                    // in scope 0 at $DIR/chained_comparison.rs:+4:13: +4:26
+    let mut _15: u32;                    // in scope 0 at $DIR/chained_comparison.rs:+4:30: +4:43
+    let mut _16: bool;                   // in scope 0 at $DIR/chained_comparison.rs:+4:12: +4:44
+    let mut _17: bool;                   // in scope 0 at $DIR/chained_comparison.rs:+1:5: +4:44
+    let mut _18: u32;                    // in scope 0 at $DIR/chained_comparison.rs:+5:13: +5:22
+    let mut _19: u32;                    // in scope 0 at $DIR/chained_comparison.rs:+5:26: +5:35
+    let mut _20: bool;                   // in scope 0 at $DIR/chained_comparison.rs:+5:12: +5:36
+
+    bb0: {
+        StorageLive(_17);                // scope 0 at $DIR/chained_comparison.rs:+1:5: +4:44
+        StorageLive(_13);                // scope 0 at $DIR/chained_comparison.rs:+1:5: +3:50
+        StorageLive(_9);                 // scope 0 at $DIR/chained_comparison.rs:+1:5: +2:36
+        StorageLive(_5);                 // scope 0 at $DIR/chained_comparison.rs:+1:5: +1:43
+        StorageLive(_3);                 // scope 0 at $DIR/chained_comparison.rs:+1:6: +1:22
+        _3 = ((*_1).0: u32);             // scope 0 at $DIR/chained_comparison.rs:+1:6: +1:22
+        StorageLive(_4);                 // scope 0 at $DIR/chained_comparison.rs:+1:26: +1:42
+        _4 = ((*_2).0: u32);             // scope 0 at $DIR/chained_comparison.rs:+1:26: +1:42
+        _5 = Eq(move _3, move _4);       // scope 0 at $DIR/chained_comparison.rs:+1:5: +1:43
+        StorageDead(_4);                 // scope 0 at $DIR/chained_comparison.rs:+1:42: +1:43
+        StorageDead(_3);                 // scope 0 at $DIR/chained_comparison.rs:+1:42: +1:43
+        switchInt(move _5) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/chained_comparison.rs:+1:5: +2:36
+    }
+
+    bb1: {
+        StorageDead(_8);                 // scope 0 at $DIR/chained_comparison.rs:+2:35: +2:36
+        StorageDead(_5);                 // scope 0 at $DIR/chained_comparison.rs:+2:35: +2:36
+        goto -> bb3;                     // scope 0 at $DIR/chained_comparison.rs:+1:5: +2:36
+    }
+
+    bb2: {
+        StorageLive(_8);                 // scope 0 at $DIR/chained_comparison.rs:+2:12: +2:36
+        StorageLive(_6);                 // scope 0 at $DIR/chained_comparison.rs:+2:13: +2:22
+        _6 = ((*_1).1: u32);             // scope 0 at $DIR/chained_comparison.rs:+2:13: +2:22
+        StorageLive(_7);                 // scope 0 at $DIR/chained_comparison.rs:+2:26: +2:35
+        _7 = ((*_2).1: u32);             // scope 0 at $DIR/chained_comparison.rs:+2:26: +2:35
+        _8 = Eq(move _6, move _7);       // scope 0 at $DIR/chained_comparison.rs:+2:12: +2:36
+        StorageDead(_7);                 // scope 0 at $DIR/chained_comparison.rs:+2:35: +2:36
+        StorageDead(_6);                 // scope 0 at $DIR/chained_comparison.rs:+2:35: +2:36
+        _9 = move _8;                    // scope 0 at $DIR/chained_comparison.rs:+1:5: +2:36
+        StorageDead(_8);                 // scope 0 at $DIR/chained_comparison.rs:+2:35: +2:36
+        StorageDead(_5);                 // scope 0 at $DIR/chained_comparison.rs:+2:35: +2:36
+        switchInt(move _9) -> [0: bb3, otherwise: bb4]; // scope 0 at $DIR/chained_comparison.rs:+1:5: +3:50
+    }
+
+    bb3: {
+        StorageDead(_12);                // scope 0 at $DIR/chained_comparison.rs:+3:49: +3:50
+        StorageDead(_9);                 // scope 0 at $DIR/chained_comparison.rs:+3:49: +3:50
+        goto -> bb5;                     // scope 0 at $DIR/chained_comparison.rs:+1:5: +3:50
+    }
+
+    bb4: {
+        StorageLive(_12);                // scope 0 at $DIR/chained_comparison.rs:+3:12: +3:50
+        StorageLive(_10);                // scope 0 at $DIR/chained_comparison.rs:+3:13: +3:29
+        _10 = ((*_1).2: u32);            // scope 0 at $DIR/chained_comparison.rs:+3:13: +3:29
+        StorageLive(_11);                // scope 0 at $DIR/chained_comparison.rs:+3:33: +3:49
+        _11 = ((*_2).2: u32);            // scope 0 at $DIR/chained_comparison.rs:+3:33: +3:49
+        _12 = Eq(move _10, move _11);    // scope 0 at $DIR/chained_comparison.rs:+3:12: +3:50
+        StorageDead(_11);                // scope 0 at $DIR/chained_comparison.rs:+3:49: +3:50
+        StorageDead(_10);                // scope 0 at $DIR/chained_comparison.rs:+3:49: +3:50
+        _13 = move _12;                  // scope 0 at $DIR/chained_comparison.rs:+1:5: +3:50
+        StorageDead(_12);                // scope 0 at $DIR/chained_comparison.rs:+3:49: +3:50
+        StorageDead(_9);                 // scope 0 at $DIR/chained_comparison.rs:+3:49: +3:50
+        switchInt(move _13) -> [0: bb5, otherwise: bb6]; // scope 0 at $DIR/chained_comparison.rs:+1:5: +4:44
+    }
+
+    bb5: {
+        StorageDead(_16);                // scope 0 at $DIR/chained_comparison.rs:+4:43: +4:44
+        StorageDead(_13);                // scope 0 at $DIR/chained_comparison.rs:+4:43: +4:44
+        goto -> bb7;                     // scope 0 at $DIR/chained_comparison.rs:+1:5: +4:44
+    }
+
+    bb6: {
+        StorageLive(_16);                // scope 0 at $DIR/chained_comparison.rs:+4:12: +4:44
+        StorageLive(_14);                // scope 0 at $DIR/chained_comparison.rs:+4:13: +4:26
+        _14 = ((*_1).3: u32);            // scope 0 at $DIR/chained_comparison.rs:+4:13: +4:26
+        StorageLive(_15);                // scope 0 at $DIR/chained_comparison.rs:+4:30: +4:43
+        _15 = ((*_2).3: u32);            // scope 0 at $DIR/chained_comparison.rs:+4:30: +4:43
+        _16 = Eq(move _14, move _15);    // scope 0 at $DIR/chained_comparison.rs:+4:12: +4:44
+        StorageDead(_15);                // scope 0 at $DIR/chained_comparison.rs:+4:43: +4:44
+        StorageDead(_14);                // scope 0 at $DIR/chained_comparison.rs:+4:43: +4:44
+        _17 = move _16;                  // scope 0 at $DIR/chained_comparison.rs:+1:5: +4:44
+        StorageDead(_16);                // scope 0 at $DIR/chained_comparison.rs:+4:43: +4:44
+        StorageDead(_13);                // scope 0 at $DIR/chained_comparison.rs:+4:43: +4:44
+        switchInt(move _17) -> [0: bb7, otherwise: bb8]; // scope 0 at $DIR/chained_comparison.rs:+1:5: +5:36
+    }
+
+    bb7: {
+        _0 = const false;                // scope 0 at $DIR/chained_comparison.rs:+1:5: +5:36
+        goto -> bb9;                     // scope 0 at $DIR/chained_comparison.rs:+1:5: +5:36
+    }
+
+    bb8: {
+        StorageLive(_20);                // scope 0 at $DIR/chained_comparison.rs:+5:12: +5:36
+        StorageLive(_18);                // scope 0 at $DIR/chained_comparison.rs:+5:13: +5:22
+        _18 = ((*_1).4: u32);            // scope 0 at $DIR/chained_comparison.rs:+5:13: +5:22
+        StorageLive(_19);                // scope 0 at $DIR/chained_comparison.rs:+5:26: +5:35
+        _19 = ((*_2).4: u32);            // scope 0 at $DIR/chained_comparison.rs:+5:26: +5:35
+        _20 = Eq(move _18, move _19);    // scope 0 at $DIR/chained_comparison.rs:+5:12: +5:36
+        StorageDead(_19);                // scope 0 at $DIR/chained_comparison.rs:+5:35: +5:36
+        StorageDead(_18);                // scope 0 at $DIR/chained_comparison.rs:+5:35: +5:36
+        _0 = move _20;                   // scope 0 at $DIR/chained_comparison.rs:+1:5: +5:36
+        goto -> bb9;                     // scope 0 at $DIR/chained_comparison.rs:+1:5: +5:36
+    }
+
+    bb9: {
+        StorageDead(_20);                // scope 0 at $DIR/chained_comparison.rs:+5:35: +5:36
+        StorageDead(_17);                // scope 0 at $DIR/chained_comparison.rs:+5:35: +5:36
+        return;                          // scope 0 at $DIR/chained_comparison.rs:+6:2: +6:2
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/chained_comparison.returning.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/chained_comparison.returning.PreCodegen.after.mir
new file mode 100644
index 00000000000..7560e1e26ce
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/chained_comparison.returning.PreCodegen.after.mir
@@ -0,0 +1,126 @@
+// MIR for `returning` after PreCodegen
+
+fn returning(_1: &Blueprint, _2: &Blueprint) -> bool {
+    debug a => _1;                       // in scope 0 at $DIR/chained_comparison.rs:+0:18: +0:19
+    debug b => _2;                       // in scope 0 at $DIR/chained_comparison.rs:+0:33: +0:34
+    let mut _0: bool;                    // return place in scope 0 at $DIR/chained_comparison.rs:+0:51: +0:55
+    let mut _3: u32;                     // in scope 0 at $DIR/chained_comparison.rs:+1:8: +1:24
+    let mut _4: u32;                     // in scope 0 at $DIR/chained_comparison.rs:+1:28: +1:44
+    let mut _5: bool;                    // in scope 0 at $DIR/chained_comparison.rs:+1:8: +1:44
+    let mut _6: u32;                     // in scope 0 at $DIR/chained_comparison.rs:+4:8: +4:17
+    let mut _7: u32;                     // in scope 0 at $DIR/chained_comparison.rs:+4:21: +4:30
+    let mut _8: bool;                    // in scope 0 at $DIR/chained_comparison.rs:+4:8: +4:30
+    let mut _9: u32;                     // in scope 0 at $DIR/chained_comparison.rs:+7:8: +7:24
+    let mut _10: u32;                    // in scope 0 at $DIR/chained_comparison.rs:+7:28: +7:44
+    let mut _11: bool;                   // in scope 0 at $DIR/chained_comparison.rs:+7:8: +7:44
+    let mut _12: u32;                    // in scope 0 at $DIR/chained_comparison.rs:+10:8: +10:21
+    let mut _13: u32;                    // in scope 0 at $DIR/chained_comparison.rs:+10:25: +10:38
+    let mut _14: bool;                   // in scope 0 at $DIR/chained_comparison.rs:+10:8: +10:38
+    let mut _15: u32;                    // in scope 0 at $DIR/chained_comparison.rs:+13:8: +13:17
+    let mut _16: u32;                    // in scope 0 at $DIR/chained_comparison.rs:+13:21: +13:30
+    let mut _17: bool;                   // in scope 0 at $DIR/chained_comparison.rs:+13:8: +13:30
+
+    bb0: {
+        StorageLive(_5);                 // scope 0 at $DIR/chained_comparison.rs:+1:8: +1:44
+        StorageLive(_3);                 // scope 0 at $DIR/chained_comparison.rs:+1:8: +1:24
+        _3 = ((*_1).0: u32);             // scope 0 at $DIR/chained_comparison.rs:+1:8: +1:24
+        StorageLive(_4);                 // scope 0 at $DIR/chained_comparison.rs:+1:28: +1:44
+        _4 = ((*_2).0: u32);             // scope 0 at $DIR/chained_comparison.rs:+1:28: +1:44
+        _5 = Ne(move _3, move _4);       // scope 0 at $DIR/chained_comparison.rs:+1:8: +1:44
+        StorageDead(_4);                 // scope 0 at $DIR/chained_comparison.rs:+1:43: +1:44
+        StorageDead(_3);                 // scope 0 at $DIR/chained_comparison.rs:+1:43: +1:44
+        switchInt(move _5) -> [0: bb1, otherwise: bb10]; // scope 0 at $DIR/chained_comparison.rs:+1:8: +1:44
+    }
+
+    bb1: {
+        StorageDead(_5);                 // scope 0 at $DIR/chained_comparison.rs:+3:5: +3:6
+        StorageLive(_8);                 // scope 0 at $DIR/chained_comparison.rs:+4:8: +4:30
+        StorageLive(_6);                 // scope 0 at $DIR/chained_comparison.rs:+4:8: +4:17
+        _6 = ((*_1).1: u32);             // scope 0 at $DIR/chained_comparison.rs:+4:8: +4:17
+        StorageLive(_7);                 // scope 0 at $DIR/chained_comparison.rs:+4:21: +4:30
+        _7 = ((*_2).1: u32);             // scope 0 at $DIR/chained_comparison.rs:+4:21: +4:30
+        _8 = Ne(move _6, move _7);       // scope 0 at $DIR/chained_comparison.rs:+4:8: +4:30
+        StorageDead(_7);                 // scope 0 at $DIR/chained_comparison.rs:+4:29: +4:30
+        StorageDead(_6);                 // scope 0 at $DIR/chained_comparison.rs:+4:29: +4:30
+        switchInt(move _8) -> [0: bb2, otherwise: bb9]; // scope 0 at $DIR/chained_comparison.rs:+4:8: +4:30
+    }
+
+    bb2: {
+        StorageDead(_8);                 // scope 0 at $DIR/chained_comparison.rs:+6:5: +6:6
+        StorageLive(_11);                // scope 0 at $DIR/chained_comparison.rs:+7:8: +7:44
+        StorageLive(_9);                 // scope 0 at $DIR/chained_comparison.rs:+7:8: +7:24
+        _9 = ((*_1).2: u32);             // scope 0 at $DIR/chained_comparison.rs:+7:8: +7:24
+        StorageLive(_10);                // scope 0 at $DIR/chained_comparison.rs:+7:28: +7:44
+        _10 = ((*_2).2: u32);            // scope 0 at $DIR/chained_comparison.rs:+7:28: +7:44
+        _11 = Ne(move _9, move _10);     // scope 0 at $DIR/chained_comparison.rs:+7:8: +7:44
+        StorageDead(_10);                // scope 0 at $DIR/chained_comparison.rs:+7:43: +7:44
+        StorageDead(_9);                 // scope 0 at $DIR/chained_comparison.rs:+7:43: +7:44
+        switchInt(move _11) -> [0: bb3, otherwise: bb8]; // scope 0 at $DIR/chained_comparison.rs:+7:8: +7:44
+    }
+
+    bb3: {
+        StorageDead(_11);                // scope 0 at $DIR/chained_comparison.rs:+9:5: +9:6
+        StorageLive(_14);                // scope 0 at $DIR/chained_comparison.rs:+10:8: +10:38
+        StorageLive(_12);                // scope 0 at $DIR/chained_comparison.rs:+10:8: +10:21
+        _12 = ((*_1).3: u32);            // scope 0 at $DIR/chained_comparison.rs:+10:8: +10:21
+        StorageLive(_13);                // scope 0 at $DIR/chained_comparison.rs:+10:25: +10:38
+        _13 = ((*_2).3: u32);            // scope 0 at $DIR/chained_comparison.rs:+10:25: +10:38
+        _14 = Ne(move _12, move _13);    // scope 0 at $DIR/chained_comparison.rs:+10:8: +10:38
+        StorageDead(_13);                // scope 0 at $DIR/chained_comparison.rs:+10:37: +10:38
+        StorageDead(_12);                // scope 0 at $DIR/chained_comparison.rs:+10:37: +10:38
+        switchInt(move _14) -> [0: bb4, otherwise: bb7]; // scope 0 at $DIR/chained_comparison.rs:+10:8: +10:38
+    }
+
+    bb4: {
+        StorageDead(_14);                // scope 0 at $DIR/chained_comparison.rs:+12:5: +12:6
+        StorageLive(_17);                // scope 0 at $DIR/chained_comparison.rs:+13:8: +13:30
+        StorageLive(_15);                // scope 0 at $DIR/chained_comparison.rs:+13:8: +13:17
+        _15 = ((*_1).4: u32);            // scope 0 at $DIR/chained_comparison.rs:+13:8: +13:17
+        StorageLive(_16);                // scope 0 at $DIR/chained_comparison.rs:+13:21: +13:30
+        _16 = ((*_2).4: u32);            // scope 0 at $DIR/chained_comparison.rs:+13:21: +13:30
+        _17 = Ne(move _15, move _16);    // scope 0 at $DIR/chained_comparison.rs:+13:8: +13:30
+        StorageDead(_16);                // scope 0 at $DIR/chained_comparison.rs:+13:29: +13:30
+        StorageDead(_15);                // scope 0 at $DIR/chained_comparison.rs:+13:29: +13:30
+        switchInt(move _17) -> [0: bb5, otherwise: bb6]; // scope 0 at $DIR/chained_comparison.rs:+13:8: +13:30
+    }
+
+    bb5: {
+        StorageDead(_17);                // scope 0 at $DIR/chained_comparison.rs:+15:5: +15:6
+        _0 = const true;                 // scope 0 at $DIR/chained_comparison.rs:+16:5: +16:9
+        goto -> bb11;                    // scope 0 at $DIR/chained_comparison.rs:+17:2: +17:2
+    }
+
+    bb6: {
+        _0 = const false;                // scope 0 at $DIR/chained_comparison.rs:+14:16: +14:21
+        StorageDead(_17);                // scope 0 at $DIR/chained_comparison.rs:+15:5: +15:6
+        goto -> bb11;                    // scope 0 at no-location
+    }
+
+    bb7: {
+        _0 = const false;                // scope 0 at $DIR/chained_comparison.rs:+11:16: +11:21
+        StorageDead(_14);                // scope 0 at $DIR/chained_comparison.rs:+12:5: +12:6
+        goto -> bb11;                    // scope 0 at no-location
+    }
+
+    bb8: {
+        _0 = const false;                // scope 0 at $DIR/chained_comparison.rs:+8:16: +8:21
+        StorageDead(_11);                // scope 0 at $DIR/chained_comparison.rs:+9:5: +9:6
+        goto -> bb11;                    // scope 0 at no-location
+    }
+
+    bb9: {
+        _0 = const false;                // scope 0 at $DIR/chained_comparison.rs:+5:16: +5:21
+        StorageDead(_8);                 // scope 0 at $DIR/chained_comparison.rs:+6:5: +6:6
+        goto -> bb11;                    // scope 0 at no-location
+    }
+
+    bb10: {
+        _0 = const false;                // scope 0 at $DIR/chained_comparison.rs:+2:16: +2:21
+        StorageDead(_5);                 // scope 0 at $DIR/chained_comparison.rs:+3:5: +3:6
+        goto -> bb11;                    // scope 0 at no-location
+    }
+
+    bb11: {
+        return;                          // scope 0 at $DIR/chained_comparison.rs:+17:2: +17:2
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/chained_comparison.rs b/tests/mir-opt/pre-codegen/chained_comparison.rs
new file mode 100644
index 00000000000..f7879140f81
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/chained_comparison.rs
@@ -0,0 +1,51 @@
+// compile-flags: -O -Zmir-opt-level=2 -Cdebuginfo=2
+// ignore-debug
+
+#![crate_type = "lib"]
+
+pub struct Blueprint {
+    pub fuel_tank_size: u32,
+    pub payload: u32,
+    pub wheel_diameter: u32,
+    pub wheel_width: u32,
+    pub storage: u32,
+}
+
+pub fn naive(a: &Blueprint, b: &Blueprint) -> bool {
+    (a.fuel_tank_size == b.fuel_tank_size)
+        && (a.payload == b.payload)
+        && (a.wheel_diameter == b.wheel_diameter)
+        && (a.wheel_width == b.wheel_width)
+        && (a.storage == b.storage)
+}
+
+pub fn bitand(a: &Blueprint, b: &Blueprint) -> bool {
+    (a.fuel_tank_size == b.fuel_tank_size)
+        & (a.payload == b.payload)
+        & (a.wheel_diameter == b.wheel_diameter)
+        & (a.wheel_width == b.wheel_width)
+        & (a.storage == b.storage)
+}
+
+pub fn returning(a: &Blueprint, b: &Blueprint) -> bool {
+    if a.fuel_tank_size != b.fuel_tank_size {
+        return false;
+    }
+    if a.payload != b.payload {
+        return false;
+    }
+    if a.wheel_diameter != b.wheel_diameter {
+        return false;
+    }
+    if a.wheel_width != b.wheel_width {
+        return false;
+    }
+    if a.storage != b.storage {
+        return false;
+    }
+    true
+}
+
+// EMIT_MIR chained_comparison.naive.PreCodegen.after.mir
+// EMIT_MIR chained_comparison.bitand.PreCodegen.after.mir
+// EMIT_MIR chained_comparison.returning.PreCodegen.after.mir
diff --git a/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir
new file mode 100644
index 00000000000..55945bbc8fc
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir
@@ -0,0 +1,144 @@
+// MIR for `checked_shl` after PreCodegen
+
+fn checked_shl(_1: u32, _2: u32) -> Option<u32> {
+    debug x => _1;                       // in scope 0 at $DIR/checked_ops.rs:+0:20: +0:21
+    debug rhs => _2;                     // in scope 0 at $DIR/checked_ops.rs:+0:28: +0:31
+    let mut _0: std::option::Option<u32>; // return place in scope 0 at $DIR/checked_ops.rs:+0:41: +0:52
+    scope 1 (inlined core::num::<impl u32>::checked_shl) { // at $DIR/checked_ops.rs:16:7: 16:23
+        debug self => _1;                // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        debug rhs => _2;                 // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        let mut _11: u32;                // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        let mut _12: bool;               // in scope 1 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        scope 2 {
+            debug a => _11;              // in scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+            debug b => _10;              // in scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        }
+        scope 3 (inlined core::num::<impl u32>::overflowing_shl) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+            debug self => _1;            // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+            debug rhs => _2;             // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+            let mut _9: u32;             // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+            let mut _10: bool;           // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+            scope 4 (inlined core::num::<impl u32>::wrapping_shl) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+                debug self => _1;        // in scope 4 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+                debug rhs => _2;         // in scope 4 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+                let mut _3: u32;         // in scope 4 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+                let mut _4: u32;         // in scope 4 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+                scope 5 {
+                    scope 6 (inlined core::num::<impl u32>::unchecked_shl) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+                        debug self => _1; // in scope 6 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+                        debug rhs => _4; // in scope 6 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+                        let mut _8: u32; // in scope 6 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                        scope 7 {
+                            scope 8 (inlined core::num::<impl u32>::unchecked_shl::conv) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                                debug x => _4; // in scope 8 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                                let mut _5: std::result::Result<u32, std::convert::Infallible>; // in scope 8 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                                let mut _7: std::option::Option<u32>; // in scope 8 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                                scope 9 {
+                                    scope 10 (inlined <u32 as TryInto<u32>>::try_into) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                                        debug self => _4; // in scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                                        scope 11 (inlined <u32 as TryFrom<u32>>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                                            debug value => _4; // in scope 11 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                                            scope 21 (inlined <u32 as Into<u32>>::into) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                                                debug self => _4; // in scope 21 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                                                scope 22 (inlined <u32 as From<u32>>::from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                                                    debug t => _4; // in scope 22 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                                                }
+                                            }
+                                        }
+                                    }
+                                    scope 12 (inlined Result::<u32, Infallible>::ok) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                                        debug self => _5; // in scope 12 at $SRC_DIR/core/src/result.rs:LL:COL
+                                        let _6: u32; // in scope 12 at $SRC_DIR/core/src/result.rs:LL:COL
+                                        scope 13 {
+                                            debug x => _6; // in scope 13 at $SRC_DIR/core/src/result.rs:LL:COL
+                                        }
+                                    }
+                                    scope 14 (inlined #[track_caller] Option::<u32>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                                        debug self => _7; // in scope 14 at $SRC_DIR/core/src/option.rs:LL:COL
+                                        let mut _13: &std::option::Option<u32>; // in scope 14 at $SRC_DIR/core/src/option.rs:LL:COL
+                                        scope 15 {
+                                            debug val => _8; // in scope 15 at $SRC_DIR/core/src/option.rs:LL:COL
+                                        }
+                                        scope 16 {
+                                            scope 18 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                                                scope 19 {
+                                                    scope 20 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                                                    }
+                                                }
+                                            }
+                                        }
+                                        scope 17 (inlined Option::<u32>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                                            debug self => _13; // in scope 17 at $SRC_DIR/core/src/option.rs:LL:COL
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    bb0: {
+        StorageLive(_10);                // scope 0 at $DIR/checked_ops.rs:+1:7: +1:23
+        StorageLive(_11);                // scope 0 at $DIR/checked_ops.rs:+1:7: +1:23
+        StorageLive(_9);                 // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        StorageLive(_4);                 // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        StorageLive(_3);                 // scope 5 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        _3 = const 31_u32;               // scope 5 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        _4 = BitAnd(_2, move _3);        // scope 5 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        StorageDead(_3);                 // scope 5 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        StorageLive(_8);                 // scope 7 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_7);                 // scope 9 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_5);                 // scope 9 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _5 = Result::<u32, Infallible>::Ok(_4); // scope 11 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+        StorageLive(_6);                 // scope 9 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _6 = move ((_5 as Ok).0: u32);   // scope 12 at $SRC_DIR/core/src/result.rs:LL:COL
+        _7 = Option::<u32>::Some(move _6); // scope 13 at $SRC_DIR/core/src/result.rs:LL:COL
+        StorageDead(_6);                 // scope 9 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_5);                 // scope 9 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageLive(_13);                // scope 9 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _8 = move ((_7 as Some).0: u32); // scope 14 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_13);                // scope 9 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        StorageDead(_7);                 // scope 9 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _9 = unchecked_shl::<u32>(_1, move _8) -> [return: bb1, unwind unreachable]; // scope 7 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+                                         // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(u32, u32) -> u32 {unchecked_shl::<u32>}, val: Value(<ZST>) }
+    }
+
+    bb1: {
+        StorageDead(_8);                 // scope 7 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        StorageDead(_4);                 // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        _10 = Ge(_2, const _);           // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        _11 = move _9;                   // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        StorageDead(_9);                 // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        StorageLive(_12);                // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+        _12 = unlikely(_10) -> [return: bb2, unwind unreachable]; // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: $SRC_DIR/core/src/num/mod.rs:LL:COL
+                                         // + literal: Const { ty: extern "rust-intrinsic" fn(bool) -> bool {unlikely}, val: Value(<ZST>) }
+    }
+
+    bb2: {
+        switchInt(move _12) -> [0: bb3, otherwise: bb4]; // scope 2 at $SRC_DIR/core/src/num/mod.rs:LL:COL
+    }
+
+    bb3: {
+        _0 = Option::<u32>::Some(_11);   // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        goto -> bb5;                     // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+    }
+
+    bb4: {
+        _0 = Option::<u32>::None;        // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        goto -> bb5;                     // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+    }
+
+    bb5: {
+        StorageDead(_12);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        StorageDead(_11);                // scope 0 at $DIR/checked_ops.rs:+1:7: +1:23
+        StorageDead(_10);                // scope 0 at $DIR/checked_ops.rs:+1:7: +1:23
+        return;                          // scope 0 at $DIR/checked_ops.rs:+2:2: +2:2
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/checked_ops.rs b/tests/mir-opt/pre-codegen/checked_ops.rs
new file mode 100644
index 00000000000..dee43b0c6f8
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/checked_ops.rs
@@ -0,0 +1,17 @@
+// compile-flags: -O -Zmir-opt-level=2 -Cdebuginfo=2
+// needs-unwind
+// ignore-debug
+// only-x86_64
+
+#![crate_type = "lib"]
+#![feature(step_trait)]
+
+// EMIT_MIR checked_ops.step_forward.PreCodegen.after.mir
+pub fn step_forward(x: u32, n: usize) -> u32 {
+    std::iter::Step::forward(x, n)
+}
+
+// EMIT_MIR checked_ops.checked_shl.PreCodegen.after.mir
+pub fn checked_shl(x: u32, rhs: u32) -> Option<u32> {
+    x.checked_shl(rhs)
+}
diff --git a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir
new file mode 100644
index 00000000000..78f68e8ffe6
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir
@@ -0,0 +1,64 @@
+// MIR for `step_forward` after PreCodegen
+
+fn step_forward(_1: u32, _2: usize) -> u32 {
+    debug x => _1;                       // in scope 0 at $DIR/checked_ops.rs:+0:21: +0:22
+    debug n => _2;                       // in scope 0 at $DIR/checked_ops.rs:+0:29: +0:30
+    let mut _0: u32;                     // return place in scope 0 at $DIR/checked_ops.rs:+0:42: +0:45
+    scope 1 (inlined <u32 as Step>::forward) { // at $DIR/checked_ops.rs:11:5: 11:35
+        debug start => _1;               // in scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        debug n => _2;                   // in scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        let _3: std::option::Option<u32>; // in scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        let mut _4: &std::option::Option<u32>; // in scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        let mut _7: bool;                // in scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        let mut _8: u32;                 // in scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        scope 2 {
+        }
+        scope 3 (inlined Option::<u32>::is_none) { // at $SRC_DIR/core/src/iter/range.rs:LL:COL
+            debug self => _4;            // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
+            let mut _6: bool;            // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
+            scope 4 (inlined Option::<u32>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                debug self => _4;        // in scope 4 at $SRC_DIR/core/src/option.rs:LL:COL
+                let mut _5: isize;       // in scope 4 at $SRC_DIR/core/src/option.rs:LL:COL
+            }
+        }
+        scope 5 (inlined core::num::<impl u32>::wrapping_add) { // at $SRC_DIR/core/src/iter/range.rs:LL:COL
+            debug self => _1;            // in scope 5 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+            debug rhs => _8;             // in scope 5 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        }
+    }
+
+    bb0: {
+        StorageLive(_7);                 // scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_4);                 // scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_3);                 // scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _3 = <u32 as Step>::forward_checked(_1, _2) -> bb1; // scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: $SRC_DIR/core/src/iter/range.rs:LL:COL
+                                         // + literal: Const { ty: fn(u32, usize) -> Option<u32> {<u32 as Step>::forward_checked}, val: Value(<ZST>) }
+    }
+
+    bb1: {
+        _4 = &_3;                        // scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_6);                 // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
+        _5 = discriminant((*_4));        // scope 4 at $SRC_DIR/core/src/option.rs:LL:COL
+        _6 = Eq(_5, const 1_isize);      // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+        _7 = Not(move _6);               // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_6);                 // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_3);                 // scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageDead(_4);                 // scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        switchInt(move _7) -> [0: bb3, otherwise: bb2]; // scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+    }
+
+    bb2: {
+        assert(!const true, "attempt to compute `{} + {}`, which would overflow", const _, const 1_u32) -> bb3; // scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+    }
+
+    bb3: {
+        StorageDead(_7);                 // scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_8);                 // scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _8 = _2 as u32 (IntToInt);       // scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _0 = Add(_1, _8);                // scope 5 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        StorageDead(_8);                 // scope 1 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        return;                          // scope 0 at $DIR/checked_ops.rs:+2:2: +2:2
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir
new file mode 100644
index 00000000000..dce9feddfc5
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir
@@ -0,0 +1,102 @@
+// MIR for `filter_mapped` after PreCodegen
+
+fn filter_mapped(_1: impl Iterator<Item = T>, _2: impl Fn(T) -> Option<U>) -> () {
+    debug iter => _1;                    // in scope 0 at $DIR/loops.rs:+0:28: +0:32
+    debug f => _2;                       // in scope 0 at $DIR/loops.rs:+0:59: +0:60
+    let mut _0: ();                      // return place in scope 0 at $DIR/loops.rs:+0:87: +0:87
+    let mut _3: std::iter::FilterMap<impl Iterator<Item = T>, impl Fn(T) -> Option<U>>; // in scope 0 at $DIR/loops.rs:+1:14: +1:32
+    let mut _4: std::iter::FilterMap<impl Iterator<Item = T>, impl Fn(T) -> Option<U>>; // in scope 0 at $DIR/loops.rs:+1:14: +1:32
+    let mut _5: std::iter::FilterMap<impl Iterator<Item = T>, impl Fn(T) -> Option<U>>; // in scope 0 at $DIR/loops.rs:+1:14: +1:32
+    let mut _6: &mut std::iter::FilterMap<impl Iterator<Item = T>, impl Fn(T) -> Option<U>>; // in scope 0 at $DIR/loops.rs:+1:14: +1:32
+    let mut _9: std::option::Option<U>;  // in scope 0 at $DIR/loops.rs:+1:14: +1:32
+    let mut _10: isize;                  // in scope 0 at $DIR/loops.rs:+1:5: +3:6
+    let _12: ();                         // in scope 0 at $DIR/loops.rs:+1:14: +1:32
+    scope 1 {
+        debug iter => _5;                // in scope 1 at $DIR/loops.rs:+1:14: +1:32
+        let _11: U;                      // in scope 1 at $DIR/loops.rs:+1:9: +1:10
+        scope 2 {
+            debug x => _11;              // in scope 2 at $DIR/loops.rs:+1:9: +1:10
+        }
+        scope 4 (inlined <FilterMap<impl Iterator<Item = T>, impl Fn(T) -> Option<U>> as Iterator>::next) { // at $DIR/loops.rs:20:14: 20:32
+            debug self => _6;            // in scope 4 at $SRC_DIR/core/src/iter/adapters/filter_map.rs:LL:COL
+            let mut _7: &mut impl Iterator<Item = T>; // in scope 4 at $SRC_DIR/core/src/iter/adapters/filter_map.rs:LL:COL
+            let mut _8: &mut impl Fn(T) -> Option<U>; // in scope 4 at $SRC_DIR/core/src/iter/adapters/filter_map.rs:LL:COL
+        }
+    }
+    scope 3 (inlined <FilterMap<impl Iterator<Item = T>, impl Fn(T) -> Option<U>> as IntoIterator>::into_iter) { // at $DIR/loops.rs:20:14: 20:32
+        debug self => _3;                // in scope 3 at $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+    }
+
+    bb0: {
+        StorageLive(_4);                 // scope 0 at $DIR/loops.rs:+1:14: +1:32
+        StorageLive(_3);                 // scope 0 at $DIR/loops.rs:+1:14: +1:32
+        _3 = <impl Iterator<Item = T> as Iterator>::filter_map::<U, impl Fn(T) -> Option<U>>(move _1, move _2) -> bb1; // scope 0 at $DIR/loops.rs:+1:14: +1:32
+                                         // mir::Constant
+                                         // + span: $DIR/loops.rs:20:19: 20:29
+                                         // + literal: Const { ty: fn(impl Iterator<Item = T>, impl Fn(T) -> Option<U>) -> FilterMap<impl Iterator<Item = T>, impl Fn(T) -> Option<U>> {<impl Iterator<Item = T> as Iterator>::filter_map::<U, impl Fn(T) -> Option<U>>}, val: Value(<ZST>) }
+    }
+
+    bb1: {
+        _4 = move _3;                    // scope 3 at $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+        StorageDead(_3);                 // scope 0 at $DIR/loops.rs:+1:31: +1:32
+        StorageLive(_5);                 // scope 0 at $DIR/loops.rs:+1:14: +1:32
+        _5 = move _4;                    // scope 0 at $DIR/loops.rs:+1:14: +1:32
+        goto -> bb2;                     // scope 1 at $DIR/loops.rs:+1:5: +3:6
+    }
+
+    bb2: {
+        StorageLive(_9);                 // scope 1 at $DIR/loops.rs:+1:14: +1:32
+        _6 = &mut _5;                    // scope 1 at $DIR/loops.rs:+1:14: +1:32
+        StorageLive(_7);                 // scope 4 at $SRC_DIR/core/src/iter/adapters/filter_map.rs:LL:COL
+        _7 = &mut ((*_6).0: impl Iterator<Item = T>); // scope 4 at $SRC_DIR/core/src/iter/adapters/filter_map.rs:LL:COL
+        StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/iter/adapters/filter_map.rs:LL:COL
+        _8 = &mut ((*_6).1: impl Fn(T) -> Option<U>); // scope 4 at $SRC_DIR/core/src/iter/adapters/filter_map.rs:LL:COL
+        _9 = <impl Iterator<Item = T> as Iterator>::find_map::<U, &mut impl Fn(T) -> Option<U>>(move _7, move _8) -> [return: bb3, unwind: bb9]; // scope 4 at $SRC_DIR/core/src/iter/adapters/filter_map.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: $SRC_DIR/core/src/iter/adapters/filter_map.rs:LL:COL
+                                         // + literal: Const { ty: for<'a> fn(&'a mut impl Iterator<Item = T>, &mut impl Fn(T) -> Option<U>) -> Option<U> {<impl Iterator<Item = T> as Iterator>::find_map::<U, &mut impl Fn(T) -> Option<U>>}, val: Value(<ZST>) }
+    }
+
+    bb3: {
+        StorageDead(_8);                 // scope 4 at $SRC_DIR/core/src/iter/adapters/filter_map.rs:LL:COL
+        StorageDead(_7);                 // scope 4 at $SRC_DIR/core/src/iter/adapters/filter_map.rs:LL:COL
+        _10 = discriminant(_9);          // scope 1 at $DIR/loops.rs:+1:14: +1:32
+        switchInt(move _10) -> [0: bb4, 1: bb6, otherwise: bb8]; // scope 1 at $DIR/loops.rs:+1:14: +1:32
+    }
+
+    bb4: {
+        StorageDead(_9);                 // scope 1 at $DIR/loops.rs:+3:5: +3:6
+        drop(_5) -> bb5;                 // scope 0 at $DIR/loops.rs:+3:5: +3:6
+    }
+
+    bb5: {
+        StorageDead(_5);                 // scope 0 at $DIR/loops.rs:+3:5: +3:6
+        StorageDead(_4);                 // scope 0 at $DIR/loops.rs:+3:5: +3:6
+        return;                          // scope 0 at $DIR/loops.rs:+4:2: +4:2
+    }
+
+    bb6: {
+        _11 = move ((_9 as Some).0: U);  // scope 1 at $DIR/loops.rs:+1:9: +1:10
+        _12 = opaque::<U>(move _11) -> [return: bb7, unwind: bb9]; // scope 2 at $DIR/loops.rs:+2:9: +2:18
+                                         // mir::Constant
+                                         // + span: $DIR/loops.rs:21:9: 21:15
+                                         // + literal: Const { ty: fn(U) {opaque::<U>}, val: Value(<ZST>) }
+    }
+
+    bb7: {
+        StorageDead(_9);                 // scope 1 at $DIR/loops.rs:+3:5: +3:6
+        goto -> bb2;                     // scope 1 at $DIR/loops.rs:+1:5: +3:6
+    }
+
+    bb8: {
+        unreachable;                     // scope 1 at $DIR/loops.rs:+1:14: +1:32
+    }
+
+    bb9 (cleanup): {
+        drop(_5) -> [return: bb10, unwind terminate]; // scope 0 at $DIR/loops.rs:+3:5: +3:6
+    }
+
+    bb10 (cleanup): {
+        resume;                          // scope 0 at $DIR/loops.rs:+0:1: +4:2
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir
new file mode 100644
index 00000000000..a5002cd6afa
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir
@@ -0,0 +1,118 @@
+// MIR for `int_range` after PreCodegen
+
+fn int_range(_1: usize, _2: usize) -> () {
+    debug start => _1;                   // in scope 0 at $DIR/loops.rs:+0:18: +0:23
+    debug end => _2;                     // in scope 0 at $DIR/loops.rs:+0:32: +0:35
+    let mut _0: ();                      // return place in scope 0 at $DIR/loops.rs:+0:44: +0:44
+    let mut _3: std::ops::Range<usize>;  // in scope 0 at $DIR/loops.rs:+1:14: +1:24
+    let mut _4: std::ops::Range<usize>;  // in scope 0 at $DIR/loops.rs:+1:14: +1:24
+    let mut _5: &mut std::ops::Range<usize>; // in scope 0 at $DIR/loops.rs:+1:14: +1:24
+    let mut _9: std::option::Option<usize>; // in scope 0 at $DIR/loops.rs:+1:14: +1:24
+    let mut _12: isize;                  // in scope 0 at $DIR/loops.rs:+1:5: +3:6
+    let _14: ();                         // in scope 0 at $DIR/loops.rs:+1:14: +1:24
+    scope 1 {
+        debug iter => _4;                // in scope 1 at $DIR/loops.rs:+1:14: +1:24
+        let _13: usize;                  // in scope 1 at $DIR/loops.rs:+1:9: +1:10
+        scope 2 {
+            debug i => _13;              // in scope 2 at $DIR/loops.rs:+1:9: +1:10
+        }
+        scope 4 (inlined iter::range::<impl Iterator for std::ops::Range<usize>>::next) { // at $DIR/loops.rs:8:14: 8:24
+            debug self => _5;            // in scope 4 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+            scope 5 (inlined <std::ops::Range<usize> as iter::range::RangeIteratorImpl>::spec_next) { // at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                debug self => _5;        // in scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                let mut _6: &usize;      // in scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                let mut _7: &usize;      // in scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                let mut _8: bool;        // in scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                let _10: usize;          // in scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                let mut _11: usize;      // in scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                scope 6 {
+                    debug old => _10;    // in scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                    scope 7 {
+                    }
+                }
+            }
+        }
+    }
+    scope 3 (inlined <std::ops::Range<usize> as IntoIterator>::into_iter) { // at $DIR/loops.rs:8:14: 8:24
+        debug self => _3;                // in scope 3 at $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+    }
+
+    bb0: {
+        _3 = std::ops::Range::<usize> { start: _1, end: _2 }; // scope 0 at $DIR/loops.rs:+1:14: +1:24
+        StorageLive(_4);                 // scope 0 at $DIR/loops.rs:+1:14: +1:24
+        _4 = move _3;                    // scope 0 at $DIR/loops.rs:+1:14: +1:24
+        goto -> bb1;                     // scope 1 at $DIR/loops.rs:+1:5: +3:6
+    }
+
+    bb1: {
+        StorageLive(_9);                 // scope 1 at $DIR/loops.rs:+1:14: +1:24
+        _5 = &mut _4;                    // scope 1 at $DIR/loops.rs:+1:14: +1:24
+        StorageLive(_10);                // scope 4 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_8);                 // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_6);                 // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _6 = &((*_5).0: usize);          // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_7);                 // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _7 = &((*_5).1: usize);          // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _8 = <usize as PartialOrd>::lt(move _6, move _7) -> bb2; // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: $SRC_DIR/core/src/iter/range.rs:LL:COL
+                                         // + literal: Const { ty: for<'a, 'b> fn(&'a usize, &'b usize) -> bool {<usize as PartialOrd>::lt}, val: Value(<ZST>) }
+    }
+
+    bb2: {
+        StorageDead(_7);                 // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageDead(_6);                 // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        switchInt(move _8) -> [0: bb3, otherwise: bb4]; // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+    }
+
+    bb3: {
+        _9 = Option::<usize>::None;      // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        goto -> bb6;                     // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+    }
+
+    bb4: {
+        _10 = ((*_5).0: usize);          // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_11);                // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _11 = <usize as Step>::forward_unchecked(_10, const 1_usize) -> bb5; // scope 7 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: $SRC_DIR/core/src/iter/range.rs:LL:COL
+                                         // + literal: Const { ty: unsafe fn(usize, usize) -> usize {<usize as Step>::forward_unchecked}, val: Value(<ZST>) }
+    }
+
+    bb5: {
+        ((*_5).0: usize) = move _11;     // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageDead(_11);                // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _9 = Option::<usize>::Some(_10); // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        goto -> bb6;                     // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+    }
+
+    bb6: {
+        StorageDead(_8);                 // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageDead(_10);                // scope 4 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _12 = discriminant(_9);          // scope 1 at $DIR/loops.rs:+1:14: +1:24
+        switchInt(move _12) -> [0: bb7, 1: bb8, otherwise: bb10]; // scope 1 at $DIR/loops.rs:+1:14: +1:24
+    }
+
+    bb7: {
+        StorageDead(_9);                 // scope 1 at $DIR/loops.rs:+3:5: +3:6
+        StorageDead(_4);                 // scope 0 at $DIR/loops.rs:+3:5: +3:6
+        return;                          // scope 0 at $DIR/loops.rs:+4:2: +4:2
+    }
+
+    bb8: {
+        _13 = ((_9 as Some).0: usize);   // scope 1 at $DIR/loops.rs:+1:9: +1:10
+        _14 = opaque::<usize>(_13) -> bb9; // scope 2 at $DIR/loops.rs:+2:9: +2:18
+                                         // mir::Constant
+                                         // + span: $DIR/loops.rs:9:9: 9:15
+                                         // + literal: Const { ty: fn(usize) {opaque::<usize>}, val: Value(<ZST>) }
+    }
+
+    bb9: {
+        StorageDead(_9);                 // scope 1 at $DIR/loops.rs:+3:5: +3:6
+        goto -> bb1;                     // scope 1 at $DIR/loops.rs:+1:5: +3:6
+    }
+
+    bb10: {
+        unreachable;                     // scope 1 at $DIR/loops.rs:+1:14: +1:24
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir
new file mode 100644
index 00000000000..bf1380b30ff
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/loops.mapped.PreCodegen.after.mir
@@ -0,0 +1,91 @@
+// MIR for `mapped` after PreCodegen
+
+fn mapped(_1: impl Iterator<Item = T>, _2: impl Fn(T) -> U) -> () {
+    debug iter => _1;                    // in scope 0 at $DIR/loops.rs:+0:21: +0:25
+    debug f => _2;                       // in scope 0 at $DIR/loops.rs:+0:52: +0:53
+    let mut _0: ();                      // return place in scope 0 at $DIR/loops.rs:+0:72: +0:72
+    let mut _3: std::iter::Map<impl Iterator<Item = T>, impl Fn(T) -> U>; // in scope 0 at $DIR/loops.rs:+1:14: +1:25
+    let mut _4: std::iter::Map<impl Iterator<Item = T>, impl Fn(T) -> U>; // in scope 0 at $DIR/loops.rs:+1:14: +1:25
+    let mut _5: std::iter::Map<impl Iterator<Item = T>, impl Fn(T) -> U>; // in scope 0 at $DIR/loops.rs:+1:14: +1:25
+    let mut _6: &mut std::iter::Map<impl Iterator<Item = T>, impl Fn(T) -> U>; // in scope 0 at $DIR/loops.rs:+1:14: +1:25
+    let mut _7: std::option::Option<U>;  // in scope 0 at $DIR/loops.rs:+1:14: +1:25
+    let mut _8: isize;                   // in scope 0 at $DIR/loops.rs:+1:5: +3:6
+    let _10: ();                         // in scope 0 at $DIR/loops.rs:+1:14: +1:25
+    scope 1 {
+        debug iter => _5;                // in scope 1 at $DIR/loops.rs:+1:14: +1:25
+        let _9: U;                       // in scope 1 at $DIR/loops.rs:+1:9: +1:10
+        scope 2 {
+            debug x => _9;               // in scope 2 at $DIR/loops.rs:+1:9: +1:10
+        }
+    }
+    scope 3 (inlined <Map<impl Iterator<Item = T>, impl Fn(T) -> U> as IntoIterator>::into_iter) { // at $DIR/loops.rs:14:14: 14:25
+        debug self => _3;                // in scope 3 at $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+    }
+
+    bb0: {
+        StorageLive(_4);                 // scope 0 at $DIR/loops.rs:+1:14: +1:25
+        StorageLive(_3);                 // scope 0 at $DIR/loops.rs:+1:14: +1:25
+        _3 = <impl Iterator<Item = T> as Iterator>::map::<U, impl Fn(T) -> U>(move _1, move _2) -> bb1; // scope 0 at $DIR/loops.rs:+1:14: +1:25
+                                         // mir::Constant
+                                         // + span: $DIR/loops.rs:14:19: 14:22
+                                         // + literal: Const { ty: fn(impl Iterator<Item = T>, impl Fn(T) -> U) -> Map<impl Iterator<Item = T>, impl Fn(T) -> U> {<impl Iterator<Item = T> as Iterator>::map::<U, impl Fn(T) -> U>}, val: Value(<ZST>) }
+    }
+
+    bb1: {
+        _4 = move _3;                    // scope 3 at $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+        StorageDead(_3);                 // scope 0 at $DIR/loops.rs:+1:24: +1:25
+        StorageLive(_5);                 // scope 0 at $DIR/loops.rs:+1:14: +1:25
+        _5 = move _4;                    // scope 0 at $DIR/loops.rs:+1:14: +1:25
+        goto -> bb2;                     // scope 1 at $DIR/loops.rs:+1:5: +3:6
+    }
+
+    bb2: {
+        StorageLive(_7);                 // scope 1 at $DIR/loops.rs:+1:14: +1:25
+        _6 = &mut _5;                    // scope 1 at $DIR/loops.rs:+1:14: +1:25
+        _7 = <Map<impl Iterator<Item = T>, impl Fn(T) -> U> as Iterator>::next(_6) -> [return: bb3, unwind: bb9]; // scope 1 at $DIR/loops.rs:+1:14: +1:25
+                                         // mir::Constant
+                                         // + span: $DIR/loops.rs:14:14: 14:25
+                                         // + literal: Const { ty: for<'a> fn(&'a mut Map<impl Iterator<Item = T>, impl Fn(T) -> U>) -> Option<<Map<impl Iterator<Item = T>, impl Fn(T) -> U> as Iterator>::Item> {<Map<impl Iterator<Item = T>, impl Fn(T) -> U> as Iterator>::next}, val: Value(<ZST>) }
+    }
+
+    bb3: {
+        _8 = discriminant(_7);           // scope 1 at $DIR/loops.rs:+1:14: +1:25
+        switchInt(move _8) -> [0: bb4, 1: bb6, otherwise: bb8]; // scope 1 at $DIR/loops.rs:+1:14: +1:25
+    }
+
+    bb4: {
+        StorageDead(_7);                 // scope 1 at $DIR/loops.rs:+3:5: +3:6
+        drop(_5) -> bb5;                 // scope 0 at $DIR/loops.rs:+3:5: +3:6
+    }
+
+    bb5: {
+        StorageDead(_5);                 // scope 0 at $DIR/loops.rs:+3:5: +3:6
+        StorageDead(_4);                 // scope 0 at $DIR/loops.rs:+3:5: +3:6
+        return;                          // scope 0 at $DIR/loops.rs:+4:2: +4:2
+    }
+
+    bb6: {
+        _9 = move ((_7 as Some).0: U);   // scope 1 at $DIR/loops.rs:+1:9: +1:10
+        _10 = opaque::<U>(move _9) -> [return: bb7, unwind: bb9]; // scope 2 at $DIR/loops.rs:+2:9: +2:18
+                                         // mir::Constant
+                                         // + span: $DIR/loops.rs:15:9: 15:15
+                                         // + literal: Const { ty: fn(U) {opaque::<U>}, val: Value(<ZST>) }
+    }
+
+    bb7: {
+        StorageDead(_7);                 // scope 1 at $DIR/loops.rs:+3:5: +3:6
+        goto -> bb2;                     // scope 1 at $DIR/loops.rs:+1:5: +3:6
+    }
+
+    bb8: {
+        unreachable;                     // scope 1 at $DIR/loops.rs:+1:14: +1:25
+    }
+
+    bb9 (cleanup): {
+        drop(_5) -> [return: bb10, unwind terminate]; // scope 0 at $DIR/loops.rs:+3:5: +3:6
+    }
+
+    bb10 (cleanup): {
+        resume;                          // scope 0 at $DIR/loops.rs:+0:1: +4:2
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/loops.rs b/tests/mir-opt/pre-codegen/loops.rs
new file mode 100644
index 00000000000..67f549a511c
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/loops.rs
@@ -0,0 +1,37 @@
+// compile-flags: -O -Zmir-opt-level=2 -g
+// needs-unwind
+// ignore-debug
+
+#![crate_type = "lib"]
+
+pub fn int_range(start: usize, end: usize) {
+    for i in start..end {
+        opaque(i)
+    }
+}
+
+pub fn mapped<T, U>(iter: impl Iterator<Item = T>, f: impl Fn(T) -> U) {
+    for x in iter.map(f) {
+        opaque(x)
+    }
+}
+
+pub fn filter_mapped<T, U>(iter: impl Iterator<Item = T>, f: impl Fn(T) -> Option<U>) {
+    for x in iter.filter_map(f) {
+        opaque(x)
+    }
+}
+
+pub fn vec_move(mut v: Vec<impl Sized>) {
+    for x in v {
+        opaque(x)
+    }
+}
+
+#[inline(never)]
+fn opaque(_: impl Sized) {}
+
+// EMIT_MIR loops.int_range.PreCodegen.after.mir
+// EMIT_MIR loops.mapped.PreCodegen.after.mir
+// EMIT_MIR loops.filter_mapped.PreCodegen.after.mir
+// EMIT_MIR loops.vec_move.PreCodegen.after.mir
diff --git a/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir
new file mode 100644
index 00000000000..6cd5a66de00
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/loops.vec_move.PreCodegen.after.mir
@@ -0,0 +1,83 @@
+// MIR for `vec_move` after PreCodegen
+
+fn vec_move(_1: Vec<impl Sized>) -> () {
+    debug v => _1;                       // in scope 0 at $DIR/loops.rs:+0:17: +0:22
+    let mut _0: ();                      // return place in scope 0 at $DIR/loops.rs:+0:41: +0:41
+    let mut _2: std::vec::IntoIter<impl Sized>; // in scope 0 at $DIR/loops.rs:+1:14: +1:15
+    let mut _3: std::vec::IntoIter<impl Sized>; // in scope 0 at $DIR/loops.rs:+1:14: +1:15
+    let mut _4: &mut std::vec::IntoIter<impl Sized>; // in scope 0 at $DIR/loops.rs:+1:14: +1:15
+    let mut _5: std::option::Option<impl Sized>; // in scope 0 at $DIR/loops.rs:+1:14: +1:15
+    let mut _6: isize;                   // in scope 0 at $DIR/loops.rs:+1:5: +3:6
+    let _8: ();                          // in scope 0 at $DIR/loops.rs:+1:14: +1:15
+    scope 1 {
+        debug iter => _3;                // in scope 1 at $DIR/loops.rs:+1:14: +1:15
+        let _7: impl Sized;              // in scope 1 at $DIR/loops.rs:+1:9: +1:10
+        scope 2 {
+            debug x => _7;               // in scope 2 at $DIR/loops.rs:+1:9: +1:10
+        }
+    }
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/loops.rs:+1:14: +1:15
+        _2 = <Vec<impl Sized> as IntoIterator>::into_iter(move _1) -> bb1; // scope 0 at $DIR/loops.rs:+1:14: +1:15
+                                         // mir::Constant
+                                         // + span: $DIR/loops.rs:26:14: 26:15
+                                         // + literal: Const { ty: fn(Vec<impl Sized>) -> <Vec<impl Sized> as IntoIterator>::IntoIter {<Vec<impl Sized> as IntoIterator>::into_iter}, val: Value(<ZST>) }
+    }
+
+    bb1: {
+        StorageLive(_3);                 // scope 0 at $DIR/loops.rs:+1:14: +1:15
+        _3 = move _2;                    // scope 0 at $DIR/loops.rs:+1:14: +1:15
+        goto -> bb2;                     // scope 1 at $DIR/loops.rs:+1:5: +3:6
+    }
+
+    bb2: {
+        StorageLive(_5);                 // scope 1 at $DIR/loops.rs:+1:14: +1:15
+        _4 = &mut _3;                    // scope 1 at $DIR/loops.rs:+1:14: +1:15
+        _5 = <std::vec::IntoIter<impl Sized> as Iterator>::next(_4) -> [return: bb3, unwind: bb9]; // scope 1 at $DIR/loops.rs:+1:14: +1:15
+                                         // mir::Constant
+                                         // + span: $DIR/loops.rs:26:14: 26:15
+                                         // + literal: Const { ty: for<'a> fn(&'a mut std::vec::IntoIter<impl Sized>) -> Option<<std::vec::IntoIter<impl Sized> as Iterator>::Item> {<std::vec::IntoIter<impl Sized> as Iterator>::next}, val: Value(<ZST>) }
+    }
+
+    bb3: {
+        _6 = discriminant(_5);           // scope 1 at $DIR/loops.rs:+1:14: +1:15
+        switchInt(move _6) -> [0: bb4, 1: bb6, otherwise: bb8]; // scope 1 at $DIR/loops.rs:+1:14: +1:15
+    }
+
+    bb4: {
+        StorageDead(_5);                 // scope 1 at $DIR/loops.rs:+3:5: +3:6
+        drop(_3) -> bb5;                 // scope 0 at $DIR/loops.rs:+3:5: +3:6
+    }
+
+    bb5: {
+        StorageDead(_3);                 // scope 0 at $DIR/loops.rs:+3:5: +3:6
+        StorageDead(_2);                 // scope 0 at $DIR/loops.rs:+3:5: +3:6
+        return;                          // scope 0 at $DIR/loops.rs:+4:2: +4:2
+    }
+
+    bb6: {
+        _7 = move ((_5 as Some).0: impl Sized); // scope 1 at $DIR/loops.rs:+1:9: +1:10
+        _8 = opaque::<impl Sized>(move _7) -> [return: bb7, unwind: bb9]; // scope 2 at $DIR/loops.rs:+2:9: +2:18
+                                         // mir::Constant
+                                         // + span: $DIR/loops.rs:27:9: 27:15
+                                         // + literal: Const { ty: fn(impl Sized) {opaque::<impl Sized>}, val: Value(<ZST>) }
+    }
+
+    bb7: {
+        StorageDead(_5);                 // scope 1 at $DIR/loops.rs:+3:5: +3:6
+        goto -> bb2;                     // scope 1 at $DIR/loops.rs:+1:5: +3:6
+    }
+
+    bb8: {
+        unreachable;                     // scope 1 at $DIR/loops.rs:+1:14: +1:15
+    }
+
+    bb9 (cleanup): {
+        drop(_3) -> [return: bb10, unwind terminate]; // scope 0 at $DIR/loops.rs:+3:5: +3:6
+    }
+
+    bb10 (cleanup): {
+        resume;                          // scope 0 at $DIR/loops.rs:+0:1: +4:2
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir
index 50e0538c133..0cf9643dfc2 100644
--- a/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/mem_replace.mem_replace.PreCodegen.after.mir
@@ -15,20 +15,18 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 {
                 scope 7 (inlined std::ptr::write::<u32>) { // at $SRC_DIR/core/src/mem/mod.rs:LL:COL
                     debug dst => _4;     // in scope 7 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
                     debug src => _2;     // in scope 7 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-                    let mut _6: *mut u32; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                     scope 8 {
                         scope 9 (inlined std::ptr::write::runtime::<u32>) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                            debug dst => _6; // in scope 9 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                            debug dst => _4; // in scope 9 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                         }
                     }
                 }
             }
             scope 4 (inlined std::ptr::read::<u32>) { // at $SRC_DIR/core/src/mem/mod.rs:LL:COL
                 debug src => _3;         // in scope 4 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-                let mut _5: *const u32;  // in scope 4 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                 scope 5 {
                     scope 6 (inlined std::ptr::read::runtime::<u32>) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                        debug src => _5; // in scope 6 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                        debug src => _3; // in scope 6 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                     }
                 }
             }
@@ -38,15 +36,11 @@ fn mem_replace(_1: &mut u32, _2: u32) -> u32 {
     bb0: {
         StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
         _3 = &raw const (*_1);           // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
         _0 = (*_3);                      // scope 5 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
         StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
         StorageLive(_4);                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
         _4 = &raw mut (*_1);             // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
-        StorageLive(_6);                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
         (*_4) = _2;                      // scope 8 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-        StorageDead(_6);                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
         StorageDead(_4);                 // scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
         return;                          // scope 0 at $DIR/mem_replace.rs:+2:2: +2:2
     }
diff --git a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir
index 089b0c23e2c..73b5678ce04 100644
--- a/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/simple_option_map.ezmap.PreCodegen.after.mir
@@ -3,24 +3,21 @@
 fn ezmap(_1: Option<i32>) -> Option<i32> {
     debug x => _1;                       // in scope 0 at $DIR/simple_option_map.rs:+0:14: +0:15
     let mut _0: std::option::Option<i32>; // return place in scope 0 at $DIR/simple_option_map.rs:+0:33: +0:44
-    let mut _5: i32;                     // in scope 0 at $DIR/simple_option_map.rs:11:25: 11:29
     scope 1 (inlined map::<i32, i32, [closure@$DIR/simple_option_map.rs:18:12: 18:15]>) { // at $DIR/simple_option_map.rs:18:5: 18:22
         debug slf => _1;                 // in scope 1 at $DIR/simple_option_map.rs:6:17: 6:20
         debug f => const ZeroSized: [closure@$DIR/simple_option_map.rs:18:12: 18:15]; // in scope 1 at $DIR/simple_option_map.rs:6:33: 6:34
         let mut _2: isize;               // in scope 1 at $DIR/simple_option_map.rs:11:9: 11:16
         let _3: i32;                     // in scope 1 at $DIR/simple_option_map.rs:11:14: 11:15
-        let mut _4: (i32,);              // in scope 1 at $DIR/simple_option_map.rs:11:25: 11:29
-        let mut _6: i32;                 // in scope 1 at $DIR/simple_option_map.rs:11:25: 11:29
+        let mut _4: i32;                 // in scope 1 at $DIR/simple_option_map.rs:11:25: 11:29
         scope 2 {
             debug x => _3;               // in scope 2 at $DIR/simple_option_map.rs:11:14: 11:15
             scope 3 (inlined ezmap::{closure#0}) { // at $DIR/simple_option_map.rs:11:25: 11:29
-                debug n => _5;           // in scope 3 at $DIR/simple_option_map.rs:+1:13: +1:14
+                debug n => _3;           // in scope 3 at $DIR/simple_option_map.rs:+1:13: +1:14
             }
         }
     }
 
     bb0: {
-        StorageLive(_3);                 // scope 0 at $DIR/simple_option_map.rs:+1:5: +1:22
         _2 = discriminant(_1);           // scope 1 at $DIR/simple_option_map.rs:10:11: 10:14
         switchInt(move _2) -> [0: bb1, 1: bb2, otherwise: bb4]; // scope 1 at $DIR/simple_option_map.rs:10:5: 10:14
     }
@@ -32,21 +29,14 @@ fn ezmap(_1: Option<i32>) -> Option<i32> {
 
     bb2: {
         _3 = ((_1 as Some).0: i32);      // scope 1 at $DIR/simple_option_map.rs:11:14: 11:15
-        StorageLive(_6);                 // scope 2 at $DIR/simple_option_map.rs:11:25: 11:29
         StorageLive(_4);                 // scope 2 at $DIR/simple_option_map.rs:11:25: 11:29
-        _4 = (move _3,);                 // scope 2 at $DIR/simple_option_map.rs:11:25: 11:29
-        StorageLive(_5);                 // scope 2 at $DIR/simple_option_map.rs:11:25: 11:29
-        _5 = move (_4.0: i32);           // scope 2 at $DIR/simple_option_map.rs:11:25: 11:29
-        _6 = Add(_5, const 1_i32);       // scope 3 at $DIR/simple_option_map.rs:+1:16: +1:21
-        StorageDead(_5);                 // scope 2 at $DIR/simple_option_map.rs:11:25: 11:29
-        StorageDead(_4);                 // scope 2 at $DIR/simple_option_map.rs:11:28: 11:29
-        _0 = Option::<i32>::Some(move _6); // scope 2 at $DIR/simple_option_map.rs:11:20: 11:30
-        StorageDead(_6);                 // scope 2 at $DIR/simple_option_map.rs:11:29: 11:30
+        _4 = Add(_3, const 1_i32);       // scope 3 at $DIR/simple_option_map.rs:+1:16: +1:21
+        _0 = Option::<i32>::Some(move _4); // scope 2 at $DIR/simple_option_map.rs:11:20: 11:30
+        StorageDead(_4);                 // scope 2 at $DIR/simple_option_map.rs:11:29: 11:30
         goto -> bb3;                     // scope 1 at $DIR/simple_option_map.rs:14:1: 14:2
     }
 
     bb3: {
-        StorageDead(_3);                 // scope 0 at $DIR/simple_option_map.rs:+1:5: +1:22
         return;                          // scope 0 at $DIR/simple_option_map.rs:+2:2: +2:2
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_filter.rs b/tests/mir-opt/pre-codegen/slice_filter.rs
new file mode 100644
index 00000000000..aba951acdd0
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/slice_filter.rs
@@ -0,0 +1,15 @@
+// compile-flags: -O -Zmir-opt-level=2 -Cdebuginfo=2
+// ignore-debug: standard library debug assertions add a panic that breaks this optimization
+
+#![crate_type = "lib"]
+
+pub fn variant_a(input: &[(usize, usize, usize, usize)]) -> usize {
+    input.iter().filter(|(a, b, c, d)| a <= c && d <= b || c <= a && b <= d).count()
+}
+
+pub fn variant_b(input: &[(usize, usize, usize, usize)]) -> usize {
+    input.iter().filter(|&&(a, b, c, d)| a <= c && d <= b || c <= a && b <= d).count()
+}
+
+// EMIT_MIR slice_filter.variant_a-{closure#0}.PreCodegen.after.mir
+// EMIT_MIR slice_filter.variant_b-{closure#0}.PreCodegen.after.mir
diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir
new file mode 100644
index 00000000000..91c8f299fdb
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir
@@ -0,0 +1,228 @@
+// MIR for `variant_a::{closure#0}` after PreCodegen
+
+fn variant_a::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:7:25: 7:39], _2: &&(usize, usize, usize, usize)) -> bool {
+    let mut _0: bool;                    // return place in scope 0 at $DIR/slice_filter.rs:+0:40: +0:40
+    let mut _3: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+    let _4: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+    let mut _5: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+    let _6: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+    let mut _7: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+    let _8: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+    let mut _9: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
+    let _10: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+    let mut _11: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:41
+    let _12: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:45: +0:46
+    let mut _13: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:45: +0:46
+    let mut _18: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:46
+    let mut _19: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:50: +0:51
+    let _20: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:55: +0:56
+    let mut _21: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:55: +0:56
+    let mut _26: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:50: +0:56
+    let mut _27: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:56
+    let mut _28: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:61
+    let _29: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:65: +0:66
+    let mut _30: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:65: +0:66
+    let mut _35: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:66
+    let mut _36: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:76
+    let mut _37: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:70: +0:71
+    let _38: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+    let mut _39: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+    let mut _44: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:70: +0:76
+    scope 1 {
+        debug a => _4;                   // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
+        debug b => _6;                   // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
+        debug c => _8;                   // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
+        debug d => _10;                  // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
+        scope 2 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:7:40: 7:46
+            debug self => _11;           // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+            debug other => _13;          // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+            let mut _14: &usize;         // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+            let mut _15: &usize;         // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+            scope 3 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
+                debug self => _14;       // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                debug other => _15;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                let mut _16: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                let mut _17: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+            }
+        }
+        scope 4 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:7:60: 7:66
+            debug self => _28;           // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+            debug other => _30;          // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+            let mut _31: &usize;         // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+            let mut _32: &usize;         // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+            scope 5 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
+                debug self => _31;       // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                debug other => _32;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                let mut _33: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                let mut _34: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+            }
+        }
+        scope 6 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:7:50: 7:56
+            debug self => _19;           // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+            debug other => _21;          // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+            let mut _22: &usize;         // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+            let mut _23: &usize;         // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+            scope 7 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
+                debug self => _22;       // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                debug other => _23;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                let mut _24: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                let mut _25: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+            }
+        }
+        scope 8 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:7:70: 7:76
+            debug self => _37;           // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+            debug other => _39;          // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+            let mut _40: &usize;         // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+            let mut _41: &usize;         // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+            scope 9 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
+                debug self => _40;       // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                debug other => _41;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                let mut _42: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+                let mut _43: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+            }
+        }
+    }
+
+    bb0: {
+        StorageLive(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+        _3 = deref_copy (*_2);           // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+        _4 = &((*_3).0: usize);          // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
+        StorageLive(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+        _5 = deref_copy (*_2);           // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+        _6 = &((*_5).1: usize);          // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
+        StorageLive(_8);                 // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+        _7 = deref_copy (*_2);           // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+        _8 = &((*_7).2: usize);          // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
+        StorageLive(_10);                // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+        _9 = deref_copy (*_2);           // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+        _10 = &((*_9).3: usize);         // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
+        StorageLive(_27);                // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+        StorageLive(_18);                // scope 1 at $DIR/slice_filter.rs:+0:40: +0:46
+        StorageLive(_11);                // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
+        _11 = &_4;                       // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
+        StorageLive(_13);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+        StorageLive(_12);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+        _12 = _8;                        // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+        _13 = &_12;                      // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+        _14 = deref_copy (*_11);         // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        _15 = deref_copy (*_13);         // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        StorageLive(_16);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        _16 = (*_14);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        StorageLive(_17);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        _17 = (*_15);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        _18 = Le(move _16, move _17);    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        StorageDead(_17);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        StorageDead(_16);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        StorageDead(_12);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+        StorageDead(_13);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+        StorageDead(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
+        switchInt(move _18) -> [0: bb1, otherwise: bb2]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+    }
+
+    bb1: {
+        StorageDead(_26);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+        StorageDead(_18);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+        goto -> bb3;                     // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+    }
+
+    bb2: {
+        StorageLive(_26);                // scope 1 at $DIR/slice_filter.rs:+0:50: +0:56
+        StorageLive(_19);                // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
+        _19 = &_10;                      // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
+        StorageLive(_21);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+        StorageLive(_20);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+        _20 = _6;                        // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+        _21 = &_20;                      // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+        _22 = deref_copy (*_19);         // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        _23 = deref_copy (*_21);         // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        StorageLive(_24);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        _24 = (*_22);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        StorageLive(_25);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        _25 = (*_23);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        _26 = Le(move _24, move _25);    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        StorageDead(_25);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        StorageDead(_24);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        StorageDead(_20);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+        StorageDead(_21);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+        StorageDead(_19);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+        _27 = move _26;                  // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
+        StorageDead(_26);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+        StorageDead(_18);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
+        switchInt(move _27) -> [0: bb3, otherwise: bb7]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+    }
+
+    bb3: {
+        StorageLive(_36);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+        StorageLive(_35);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:66
+        StorageLive(_28);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
+        _28 = &_8;                       // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
+        StorageLive(_30);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+        StorageLive(_29);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+        _29 = _4;                        // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+        _30 = &_29;                      // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+        _31 = deref_copy (*_28);         // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        _32 = deref_copy (*_30);         // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        StorageLive(_33);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        _33 = (*_31);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        StorageLive(_34);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        _34 = (*_32);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        _35 = Le(move _33, move _34);    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        StorageDead(_34);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        StorageDead(_33);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        StorageDead(_29);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+        StorageDead(_30);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+        StorageDead(_28);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
+        switchInt(move _35) -> [0: bb4, otherwise: bb5]; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+    }
+
+    bb4: {
+        _36 = const false;               // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+        goto -> bb6;                     // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+    }
+
+    bb5: {
+        StorageLive(_44);                // scope 1 at $DIR/slice_filter.rs:+0:70: +0:76
+        StorageLive(_37);                // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
+        _37 = &_6;                       // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
+        StorageLive(_39);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+        StorageLive(_38);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+        _38 = _10;                       // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+        _39 = &_38;                      // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+        _40 = deref_copy (*_37);         // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        _41 = deref_copy (*_39);         // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        StorageLive(_42);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        _42 = (*_40);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        StorageLive(_43);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        _43 = (*_41);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        _44 = Le(move _42, move _43);    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        StorageDead(_43);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        StorageDead(_42);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
+        StorageDead(_38);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+        StorageDead(_39);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+        StorageDead(_37);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+        _36 = move _44;                  // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+        goto -> bb6;                     // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
+    }
+
+    bb6: {
+        StorageDead(_44);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+        StorageDead(_35);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+        _0 = move _36;                   // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+        goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+    }
+
+    bb7: {
+        _0 = const true;                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+        goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
+    }
+
+    bb8: {
+        StorageDead(_36);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+        StorageDead(_27);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
+        StorageDead(_10);                // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+        StorageDead(_8);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+        StorageDead(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+        StorageDead(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
+        return;                          // scope 0 at $DIR/slice_filter.rs:+0:76: +0:76
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir
new file mode 100644
index 00000000000..9f5fe95a8b4
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/slice_filter.variant_b-{closure#0}.PreCodegen.after.mir
@@ -0,0 +1,92 @@
+// MIR for `variant_b::{closure#0}` after PreCodegen
+
+fn variant_b::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:11:25: 11:41], _2: &&(usize, usize, usize, usize)) -> bool {
+    let mut _0: bool;                    // return place in scope 0 at $DIR/slice_filter.rs:+0:42: +0:42
+    let mut _3: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
+    let _4: usize;                       // in scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
+    let mut _5: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
+    let _6: usize;                       // in scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
+    let mut _7: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
+    let _8: usize;                       // in scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
+    let mut _9: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
+    let _10: usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
+    let mut _11: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:42: +0:48
+    let mut _12: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:52: +0:58
+    let mut _13: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:42: +0:58
+    let mut _14: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:62: +0:68
+    let mut _15: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:62: +0:78
+    let mut _16: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:72: +0:78
+    scope 1 {
+        debug a => _4;                   // in scope 1 at $DIR/slice_filter.rs:+0:29: +0:30
+        debug b => _6;                   // in scope 1 at $DIR/slice_filter.rs:+0:32: +0:33
+        debug c => _8;                   // in scope 1 at $DIR/slice_filter.rs:+0:35: +0:36
+        debug d => _10;                  // in scope 1 at $DIR/slice_filter.rs:+0:38: +0:39
+    }
+
+    bb0: {
+        _3 = deref_copy (*_2);           // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
+        _4 = ((*_3).0: usize);           // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
+        _5 = deref_copy (*_2);           // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
+        _6 = ((*_5).1: usize);           // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
+        _7 = deref_copy (*_2);           // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
+        _8 = ((*_7).2: usize);           // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
+        _9 = deref_copy (*_2);           // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
+        _10 = ((*_9).3: usize);          // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
+        StorageLive(_13);                // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
+        StorageLive(_11);                // scope 1 at $DIR/slice_filter.rs:+0:42: +0:48
+        _11 = Le(_4, _8);                // scope 1 at $DIR/slice_filter.rs:+0:42: +0:48
+        switchInt(move _11) -> [0: bb1, otherwise: bb2]; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
+    }
+
+    bb1: {
+        StorageDead(_12);                // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
+        StorageDead(_11);                // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
+        goto -> bb3;                     // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
+    }
+
+    bb2: {
+        StorageLive(_12);                // scope 1 at $DIR/slice_filter.rs:+0:52: +0:58
+        _12 = Le(_10, _6);               // scope 1 at $DIR/slice_filter.rs:+0:52: +0:58
+        _13 = move _12;                  // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
+        StorageDead(_12);                // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
+        StorageDead(_11);                // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
+        switchInt(move _13) -> [0: bb3, otherwise: bb7]; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
+    }
+
+    bb3: {
+        StorageLive(_15);                // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+        StorageLive(_14);                // scope 1 at $DIR/slice_filter.rs:+0:62: +0:68
+        _14 = Le(_8, _4);                // scope 1 at $DIR/slice_filter.rs:+0:62: +0:68
+        switchInt(move _14) -> [0: bb4, otherwise: bb5]; // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+    }
+
+    bb4: {
+        _15 = const false;               // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+        goto -> bb6;                     // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+    }
+
+    bb5: {
+        StorageLive(_16);                // scope 1 at $DIR/slice_filter.rs:+0:72: +0:78
+        _16 = Le(_6, _10);               // scope 1 at $DIR/slice_filter.rs:+0:72: +0:78
+        _15 = move _16;                  // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+        goto -> bb6;                     // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
+    }
+
+    bb6: {
+        StorageDead(_16);                // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
+        StorageDead(_14);                // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
+        _0 = move _15;                   // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
+        goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
+    }
+
+    bb7: {
+        _0 = const true;                 // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
+        goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
+    }
+
+    bb8: {
+        StorageDead(_15);                // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
+        StorageDead(_13);                // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
+        return;                          // scope 0 at $DIR/slice_filter.rs:+0:78: +0:78
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.mir
index b05d44f4d60..6c306280536 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.mir
@@ -21,19 +21,17 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
                     debug self => _2;    // in scope 4 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                     debug slice => _6;   // in scope 4 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                     let mut _7: *mut u32; // in scope 4 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                    let mut _10: usize;  // in scope 4 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                    let mut _11: *mut [u32]; // in scope 4 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                     scope 5 {
                         debug this => _2; // in scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                         scope 6 {
                             scope 7 (inlined <usize as SliceIndex<[T]>>::get_unchecked_mut::runtime::<u32>) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                                debug this => _10; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                                debug slice => _11; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                                debug this => _2; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                                debug slice => _6; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                                 scope 8 (inlined ptr::mut_ptr::<impl *mut [u32]>::len) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                                    debug self => _11; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                    let mut _12: *const [u32]; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                    debug self => _6; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                    let mut _10: *const [u32]; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                     scope 9 (inlined std::ptr::metadata::<[u32]>) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                        debug ptr => _12; // in scope 9 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                        debug ptr => _10; // in scope 9 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
                                         scope 10 {
                                         }
                                     }
@@ -81,14 +79,10 @@ fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> {
         StorageLive(_6);                 // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         _6 = &raw mut (*_1);             // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageLive(_10);                // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageLive(_11);                // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageLive(_12);                // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageLive(_7);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         _7 = _6 as *mut u32 (PtrToPtr);  // scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
         _8 = Offset(_7, _2);             // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
         StorageDead(_7);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageDead(_12);                // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageDead(_11);                // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageDead(_10);                // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageDead(_6);                 // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         _9 = &mut (*_8);                 // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
diff --git a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.mir
index 6d9ec5d9a27..727ccc1de53 100644
--- a/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/slice_index.slice_get_unchecked_mut_range.PreCodegen.after.mir
@@ -4,65 +4,63 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
     debug slice => _1;                   // in scope 0 at $DIR/slice_index.rs:+0:45: +0:50
     debug index => _2;                   // in scope 0 at $DIR/slice_index.rs:+0:64: +0:69
     let mut _0: &mut [u32];              // return place in scope 0 at $DIR/slice_index.rs:+0:88: +0:98
+    let mut _3: usize;                   // in scope 0 at $DIR/slice_index.rs:+1:29: +1:34
+    let mut _4: usize;                   // in scope 0 at $DIR/slice_index.rs:+1:29: +1:34
     scope 1 (inlined core::slice::<impl [u32]>::get_unchecked_mut::<std::ops::Range<usize>>) { // at $DIR/slice_index.rs:26:11: 26:35
         debug self => _1;                // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        debug index => _2;               // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        let mut _3: *mut [u32];          // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        let mut _15: *mut [u32];         // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        debug index => std::ops::Range<usize>{ .0 => _3, .1 => _4, }; // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        let mut _5: *mut [u32];          // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        let mut _14: *mut [u32];         // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         scope 2 {
             scope 3 (inlined <std::ops::Range<usize> as SliceIndex<[u32]>>::get_unchecked_mut) { // at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-                debug self => _2;        // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                debug slice => _3;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let mut _4: usize;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let mut _5: usize;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                debug self => std::ops::Range<usize>{ .0 => _3, .1 => _4, }; // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                debug slice => _5;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                 let mut _7: *mut u32;    // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let mut _8: usize;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let mut _9: *mut u32;    // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let mut _10: usize;      // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let _16: std::ops::Range<usize>; // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                let mut _17: std::ops::Range<usize>; // in scope 3 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                let mut _18: *mut [u32]; // in scope 3 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                let mut _8: *mut u32;    // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                let mut _9: usize;       // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                let _16: usize;          // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                let _17: usize;          // in scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                 scope 4 {
-                    debug this => _16;   // in scope 4 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+                    debug this => std::ops::Range<usize>{ .0 => _16, .1 => _17, }; // in scope 4 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                     scope 5 {
                         let _6: usize;   // in scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                         scope 6 {
                             debug new_len => _6; // in scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                             scope 11 (inlined ptr::mut_ptr::<impl *mut [u32]>::as_mut_ptr) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                                debug self => _3; // in scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                debug self => _5; // in scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                             }
                             scope 12 (inlined ptr::mut_ptr::<impl *mut u32>::add) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL
                                 debug self => _7; // in scope 12 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                debug count => _8; // in scope 12 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                debug count => _3; // in scope 12 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                 scope 13 {
                                 }
                             }
                             scope 14 (inlined slice_from_raw_parts_mut::<u32>) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                                debug data => _9; // in scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-                                debug len => _10; // in scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-                                let mut _11: *mut (); // in scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+                                debug data => _8; // in scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+                                debug len => _9; // in scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+                                let mut _10: *mut (); // in scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
                                 scope 15 (inlined ptr::mut_ptr::<impl *mut u32>::cast::<()>) { // at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-                                    debug self => _9; // in scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                    debug self => _8; // in scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                 }
                                 scope 16 (inlined std::ptr::from_raw_parts_mut::<[u32]>) { // at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-                                    debug data_address => _11; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-                                    debug metadata => _10; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-                                    let mut _12: *const (); // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-                                    let mut _13: std::ptr::metadata::PtrComponents<[u32]>; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-                                    let mut _14: std::ptr::metadata::PtrRepr<[u32]>; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    debug data_address => _10; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    debug metadata => _9; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    let mut _11: *const (); // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    let mut _12: std::ptr::metadata::PtrComponents<[u32]>; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    let mut _13: std::ptr::metadata::PtrRepr<[u32]>; // in scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
                                     scope 17 {
                                     }
                                 }
                             }
                         }
                         scope 7 (inlined <std::ops::Range<usize> as SliceIndex<[T]>>::get_unchecked_mut::runtime::<u32>) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                            debug this => _17; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                            debug slice => _18; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                            debug this => std::ops::Range<usize>{ .0 => _16, .1 => _17, }; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                            debug slice => _5; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                             scope 8 (inlined ptr::mut_ptr::<impl *mut [u32]>::len) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL
-                                debug self => _18; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                let mut _19: *const [u32]; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                debug self => _5; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                let mut _15: *const [u32]; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                 scope 9 (inlined std::ptr::metadata::<[u32]>) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                    debug ptr => _19; // in scope 9 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+                                    debug ptr => _15; // in scope 9 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
                                     scope 10 {
                                     }
                                 }
@@ -75,60 +73,51 @@ fn slice_get_unchecked_mut_range(_1: &mut [u32], _2: std::ops::Range<usize>) ->
     }
 
     bb0: {
+        _3 = move (_2.0: usize);         // scope 0 at $DIR/slice_index.rs:+1:29: +1:34
+        _4 = move (_2.1: usize);         // scope 0 at $DIR/slice_index.rs:+1:29: +1:34
+        StorageLive(_14);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _5 = &raw mut (*_1);             // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         StorageLive(_15);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        _3 = &raw mut (*_1);             // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         StorageLive(_16);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         StorageLive(_17);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageLive(_18);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageLive(_19);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         StorageLive(_6);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageLive(_4);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _4 = (_2.1: usize);              // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageLive(_5);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _5 = (_2.0: usize);              // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _6 = unchecked_sub::<usize>(move _4, move _5) -> [return: bb1, unwind unreachable]; // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _6 = unchecked_sub::<usize>(_4, _3) -> [return: bb1, unwind unreachable]; // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
                                          // mir::Constant
                                          // + span: $SRC_DIR/core/src/slice/index.rs:LL:COL
                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize, usize) -> usize {unchecked_sub::<usize>}, val: Value(<ZST>) }
     }
 
     bb1: {
-        StorageDead(_5);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageDead(_4);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageLive(_9);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageLive(_7);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _7 = _3 as *mut u32 (PtrToPtr);  // scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
         StorageLive(_8);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _8 = (_2.0: usize);              // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _9 = Offset(_7, _8);             // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-        StorageDead(_8);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageLive(_7);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _7 = _5 as *mut u32 (PtrToPtr);  // scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+        _8 = Offset(_7, _3);             // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
         StorageDead(_7);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageLive(_10);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        _10 = _6;                        // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageLive(_11);                // scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-        _11 = _9 as *mut () (PtrToPtr);  // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-        StorageLive(_14);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        StorageLive(_9);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _9 = _6;                         // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageLive(_10);                // scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+        _10 = _8 as *mut () (PtrToPtr);  // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
         StorageLive(_13);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
         StorageLive(_12);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        _12 = _11 as *const () (Pointer(MutToConstPointer)); // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        _13 = ptr::metadata::PtrComponents::<[u32]> { data_address: move _12, metadata: _10 }; // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        StorageLive(_11);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        _11 = _10 as *const () (Pointer(MutToConstPointer)); // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        _12 = ptr::metadata::PtrComponents::<[u32]> { data_address: move _11, metadata: _9 }; // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        StorageDead(_11);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        _13 = ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _12 }; // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
         StorageDead(_12);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        _14 = ptr::metadata::PtrRepr::<[u32]> { const_ptr: move _13 }; // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        StorageDead(_13);                // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        _15 = (_14.1: *mut [u32]);       // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        StorageDead(_14);                // scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
-        StorageDead(_11);                // scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-        StorageDead(_10);                // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        _14 = (_13.1: *mut [u32]);       // scope 17 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        StorageDead(_13);                // scope 16 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL
+        StorageDead(_10);                // scope 14 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
         StorageDead(_9);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
+        StorageDead(_8);                 // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL
         StorageDead(_6);                 // scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL
-        StorageDead(_19);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageDead(_18);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         StorageDead(_17);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         StorageDead(_16);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageDead(_3);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        _0 = &mut (*_15);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
-        StorageDead(_15);                // scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageDead(_15);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _0 = &mut (*_14);                // scope 2 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageDead(_14);                // scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
         return;                          // scope 0 at $DIR/slice_index.rs:+2:2: +2:2
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.mir
new file mode 100644
index 00000000000..4dd11c1e529
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.mir
@@ -0,0 +1,213 @@
+// MIR for `enumerated_loop` after PreCodegen
+
+fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
+    debug slice => _1;                   // in scope 0 at $DIR/slice_iter.rs:+0:31: +0:36
+    debug f => _2;                       // in scope 0 at $DIR/slice_iter.rs:+0:47: +0:48
+    let mut _0: ();                      // return place in scope 0 at $DIR/slice_iter.rs:+0:70: +0:70
+    let mut _13: std::slice::Iter<'_, T>; // in scope 0 at $DIR/slice_iter.rs:+1:19: +1:31
+    let mut _14: std::iter::Enumerate<std::slice::Iter<'_, T>>; // in scope 0 at $DIR/slice_iter.rs:+1:19: +1:43
+    let mut _15: std::iter::Enumerate<std::slice::Iter<'_, T>>; // in scope 0 at $DIR/slice_iter.rs:+1:19: +1:43
+    let mut _16: &mut std::iter::Enumerate<std::slice::Iter<'_, T>>; // in scope 0 at $DIR/slice_iter.rs:+1:19: +1:43
+    let mut _17: std::option::Option<(usize, &T)>; // in scope 0 at $DIR/slice_iter.rs:+1:19: +1:43
+    let mut _18: isize;                  // in scope 0 at $DIR/slice_iter.rs:+1:5: +3:6
+    let mut _21: &impl Fn(usize, &T);    // in scope 0 at $DIR/slice_iter.rs:+2:9: +2:10
+    let mut _22: (usize, &T);            // in scope 0 at $DIR/slice_iter.rs:+2:9: +2:16
+    let _23: ();                         // in scope 0 at $DIR/slice_iter.rs:+1:19: +1:43
+    scope 1 {
+        debug iter => _15;               // in scope 1 at $DIR/slice_iter.rs:+1:19: +1:43
+        let _19: usize;                  // in scope 1 at $DIR/slice_iter.rs:+1:10: +1:11
+        let _20: &T;                     // in scope 1 at $DIR/slice_iter.rs:+1:13: +1:14
+        scope 2 {
+            debug i => _19;              // in scope 2 at $DIR/slice_iter.rs:+1:10: +1:11
+            debug x => _20;              // in scope 2 at $DIR/slice_iter.rs:+1:13: +1:14
+        }
+    }
+    scope 3 (inlined core::slice::<impl [T]>::iter) { // at $DIR/slice_iter.rs:42:25: 42:31
+        debug self => _1;                // in scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        scope 4 (inlined std::slice::Iter::<'_, T>::new) { // at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+            debug slice => _1;           // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let _4: *const T;            // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _5: bool;            // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _6: usize;           // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _8: usize;           // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _9: *mut T;          // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _11: std::ptr::NonNull<T>; // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            let mut _12: *const T;       // in scope 4 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+            scope 5 {
+                debug ptr => _4;         // in scope 5 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                scope 6 {
+                    let _7: *const T;    // in scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                    scope 7 {
+                        debug end => _7; // in scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                        scope 13 (inlined NonNull::<T>::new_unchecked) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                            debug ptr => _9; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+                            let mut _10: *const T; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+                            scope 14 {
+                                scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                                    debug ptr => _9; // in scope 15 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                                    scope 16 (inlined ptr::mut_ptr::<impl *mut T>::is_null) { // at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+                                        debug self => _9; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                        let mut _24: *mut u8; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                        scope 17 {
+                                            scope 18 (inlined ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                debug ptr => _24; // in scope 18 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                scope 19 (inlined ptr::mut_ptr::<impl *mut u8>::addr) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                    debug self => _24; // in scope 19 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                    scope 20 {
+                                                        scope 21 (inlined ptr::mut_ptr::<impl *mut u8>::cast::<()>) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                            debug self => _24; // in scope 21 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    scope 9 (inlined invalid::<T>) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                        debug addr => _8; // in scope 9 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+                        scope 10 {
+                        }
+                    }
+                    scope 11 (inlined ptr::const_ptr::<impl *const T>::add) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                        debug self => _4; // in scope 11 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+                        debug count => _6; // in scope 11 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+                        scope 12 {
+                        }
+                    }
+                }
+            }
+            scope 8 (inlined core::slice::<impl [T]>::as_ptr) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                debug self => _1;        // in scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+                let mut _3: *const [T];  // in scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+            }
+        }
+    }
+    scope 22 (inlined <std::slice::Iter<'_, T> as Iterator>::enumerate) { // at $DIR/slice_iter.rs:42:32: 42:43
+        debug self => _13;               // in scope 22 at $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+        scope 23 (inlined Enumerate::<std::slice::Iter<'_, T>>::new) { // at $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+            debug iter => _13;           // in scope 23 at $SRC_DIR/core/src/iter/adapters/enumerate.rs:LL:COL
+        }
+    }
+    scope 24 (inlined <Enumerate<std::slice::Iter<'_, T>> as IntoIterator>::into_iter) { // at $DIR/slice_iter.rs:42:19: 42:43
+        debug self => _14;               // in scope 24 at $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+    }
+
+    bb0: {
+        StorageLive(_13);                // scope 0 at $DIR/slice_iter.rs:+1:19: +1:31
+        StorageLive(_4);                 // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_3);                 // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _3 = &raw const (*_1);           // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _4 = move _3 as *const T (PtrToPtr); // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageDead(_3);                 // scope 8 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        StorageLive(_7);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_5);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _5 = const _;                    // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        switchInt(move _5) -> [0: bb1, otherwise: bb2]; // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+    }
+
+    bb1: {
+        StorageLive(_6);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _6 = Len((*_1));                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _7 = Offset(_4, _6);             // scope 12 at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+        StorageDead(_6);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        goto -> bb3;                     // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+    }
+
+    bb2: {
+        StorageLive(_8);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _8 = Len((*_1));                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _7 = _8 as *const T (Transmute); // scope 10 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+        StorageDead(_8);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        goto -> bb3;                     // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+    }
+
+    bb3: {
+        StorageDead(_5);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_11);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_9);                 // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _9 = _4 as *mut T (PtrToPtr);    // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_10);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_24);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _10 = _9 as *const T (Pointer(MutToConstPointer)); // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+        _11 = NonNull::<T> { pointer: _10 }; // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
+        StorageDead(_24);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_10);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_9);                 // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageLive(_12);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _12 = _7;                        // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        _13 = std::slice::Iter::<'_, T> { ptr: move _11, end: move _12, _marker: const ZeroSized: PhantomData<&T> }; // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: no-location
+                                         // + literal: Const { ty: PhantomData<&T>, val: Value(<ZST>) }
+                                         // adt
+                                         // + user_ty: UserType(1)
+        StorageDead(_12);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_11);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_7);                 // scope 6 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
+        StorageDead(_4);                 // scope 3 at $SRC_DIR/core/src/slice/mod.rs:LL:COL
+        _14 = Enumerate::<std::slice::Iter<'_, T>> { iter: move _13, count: const 0_usize }; // scope 23 at $SRC_DIR/core/src/iter/adapters/enumerate.rs:LL:COL
+        StorageDead(_13);                // scope 0 at $DIR/slice_iter.rs:+1:42: +1:43
+        StorageLive(_15);                // scope 0 at $DIR/slice_iter.rs:+1:19: +1:43
+        _15 = move _14;                  // scope 0 at $DIR/slice_iter.rs:+1:19: +1:43
+        goto -> bb4;                     // scope 1 at $DIR/slice_iter.rs:+1:5: +3:6
+    }
+
+    bb4: {
+        StorageLive(_17);                // scope 1 at $DIR/slice_iter.rs:+1:19: +1:43
+        _16 = &mut _15;                  // scope 1 at $DIR/slice_iter.rs:+1:19: +1:43
+        _17 = <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next(_16) -> [return: bb5, unwind: bb11]; // scope 1 at $DIR/slice_iter.rs:+1:19: +1:43
+                                         // mir::Constant
+                                         // + span: $DIR/slice_iter.rs:42:19: 42:43
+                                         // + literal: Const { ty: for<'a> fn(&'a mut Enumerate<std::slice::Iter<'_, T>>) -> Option<<Enumerate<std::slice::Iter<'_, T>> as Iterator>::Item> {<Enumerate<std::slice::Iter<'_, T>> as Iterator>::next}, val: Value(<ZST>) }
+    }
+
+    bb5: {
+        _18 = discriminant(_17);         // scope 1 at $DIR/slice_iter.rs:+1:19: +1:43
+        switchInt(move _18) -> [0: bb6, 1: bb8, otherwise: bb10]; // scope 1 at $DIR/slice_iter.rs:+1:19: +1:43
+    }
+
+    bb6: {
+        StorageDead(_17);                // scope 1 at $DIR/slice_iter.rs:+3:5: +3:6
+        StorageDead(_15);                // scope 0 at $DIR/slice_iter.rs:+3:5: +3:6
+        drop(_2) -> bb7;                 // scope 0 at $DIR/slice_iter.rs:+4:1: +4:2
+    }
+
+    bb7: {
+        return;                          // scope 0 at $DIR/slice_iter.rs:+4:2: +4:2
+    }
+
+    bb8: {
+        _19 = (((_17 as Some).0: (usize, &T)).0: usize); // scope 1 at $DIR/slice_iter.rs:+1:10: +1:11
+        _20 = (((_17 as Some).0: (usize, &T)).1: &T); // scope 1 at $DIR/slice_iter.rs:+1:13: +1:14
+        StorageLive(_21);                // scope 2 at $DIR/slice_iter.rs:+2:9: +2:10
+        _21 = &_2;                       // scope 2 at $DIR/slice_iter.rs:+2:9: +2:10
+        StorageLive(_22);                // scope 2 at $DIR/slice_iter.rs:+2:9: +2:16
+        _22 = (_19, _20);                // scope 2 at $DIR/slice_iter.rs:+2:9: +2:16
+        _23 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _21, move _22) -> [return: bb9, unwind: bb11]; // scope 2 at $DIR/slice_iter.rs:+2:9: +2:16
+                                         // mir::Constant
+                                         // + span: $DIR/slice_iter.rs:43:9: 43:10
+                                         // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a impl Fn(usize, &T), (usize, &T)) -> <impl Fn(usize, &T) as FnOnce<(usize, &T)>>::Output {<impl Fn(usize, &T) as Fn<(usize, &T)>>::call}, val: Value(<ZST>) }
+    }
+
+    bb9: {
+        StorageDead(_22);                // scope 2 at $DIR/slice_iter.rs:+2:15: +2:16
+        StorageDead(_21);                // scope 2 at $DIR/slice_iter.rs:+2:15: +2:16
+        StorageDead(_17);                // scope 1 at $DIR/slice_iter.rs:+3:5: +3:6
+        goto -> bb4;                     // scope 1 at $DIR/slice_iter.rs:+1:5: +3:6
+    }
+
+    bb10: {
+        unreachable;                     // scope 1 at $DIR/slice_iter.rs:+1:19: +1:43
+    }
+
+    bb11 (cleanup): {
+        drop(_2) -> [return: bb12, unwind terminate]; // scope 0 at $DIR/slice_iter.rs:+4:1: +4:2
+    }
+
+    bb12 (cleanup): {
+        resume;                          // scope 0 at $DIR/slice_iter.rs:+0:1: +4:2
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.mir
index 0cf1d68d18a..0c18fb84bcd 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.mir
@@ -39,21 +39,20 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                         scope 13 (inlined NonNull::<T>::new_unchecked) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
                             debug ptr => _9; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
                             let mut _10: *const T; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
-                            let mut _22: *mut T; // in scope 13 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                             scope 14 {
                                 scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                                    debug ptr => _22; // in scope 15 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                                    debug ptr => _9; // in scope 15 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                                     scope 16 (inlined ptr::mut_ptr::<impl *mut T>::is_null) { // at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
-                                        debug self => _22; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                        let mut _23: *mut u8; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                        debug self => _9; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                        let mut _22: *mut u8; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                         scope 17 {
                                             scope 18 (inlined ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                                debug ptr => _23; // in scope 18 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                debug ptr => _22; // in scope 18 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                                 scope 19 (inlined ptr::mut_ptr::<impl *mut u8>::addr) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                                    debug self => _23; // in scope 19 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                    debug self => _22; // in scope 19 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                                     scope 20 {
                                                         scope 21 (inlined ptr::mut_ptr::<impl *mut u8>::cast::<()>) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                                            debug self => _23; // in scope 21 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                            debug self => _22; // in scope 21 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                                         }
                                                     }
                                                 }
@@ -122,10 +121,8 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
         _9 = _4 as *mut T (PtrToPtr);    // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
         StorageLive(_10);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
         StorageLive(_22);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageLive(_23);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
         _10 = _9 as *const T (Pointer(MutToConstPointer)); // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
         _11 = NonNull::<T> { pointer: _10 }; // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
-        StorageDead(_23);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
         StorageDead(_22);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
         StorageDead(_10);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
         StorageDead(_9);                 // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.mir
new file mode 100644
index 00000000000..ca7a4a64f45
--- /dev/null
+++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.mir
@@ -0,0 +1,155 @@
+// MIR for `range_loop` after PreCodegen
+
+fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
+    debug slice => _1;                   // in scope 0 at $DIR/slice_iter.rs:+0:26: +0:31
+    debug f => _2;                       // in scope 0 at $DIR/slice_iter.rs:+0:42: +0:43
+    let mut _0: ();                      // return place in scope 0 at $DIR/slice_iter.rs:+0:65: +0:65
+    let mut _3: usize;                   // in scope 0 at $DIR/slice_iter.rs:+1:17: +1:28
+    let mut _4: std::ops::Range<usize>;  // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:28
+    let mut _5: std::ops::Range<usize>;  // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:28
+    let mut _6: &mut std::ops::Range<usize>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:28
+    let mut _10: std::option::Option<usize>; // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:28
+    let mut _13: isize;                  // in scope 0 at $DIR/slice_iter.rs:+1:5: +4:6
+    let mut _15: usize;                  // in scope 0 at $DIR/slice_iter.rs:+2:18: +2:26
+    let mut _16: bool;                   // in scope 0 at $DIR/slice_iter.rs:+2:18: +2:26
+    let mut _18: &impl Fn(usize, &T);    // in scope 0 at $DIR/slice_iter.rs:+3:9: +3:10
+    let mut _19: (usize, &T);            // in scope 0 at $DIR/slice_iter.rs:+3:9: +3:16
+    let _20: ();                         // in scope 0 at $DIR/slice_iter.rs:+1:14: +1:28
+    scope 1 {
+        debug iter => _5;                // in scope 1 at $DIR/slice_iter.rs:+1:14: +1:28
+        let _14: usize;                  // in scope 1 at $DIR/slice_iter.rs:+1:9: +1:10
+        scope 2 {
+            debug i => _14;              // in scope 2 at $DIR/slice_iter.rs:+1:9: +1:10
+            let _17: &T;                 // in scope 2 at $DIR/slice_iter.rs:+2:13: +2:14
+            scope 3 {
+                debug x => _17;          // in scope 3 at $DIR/slice_iter.rs:+2:13: +2:14
+            }
+        }
+        scope 5 (inlined iter::range::<impl Iterator for std::ops::Range<usize>>::next) { // at $DIR/slice_iter.rs:49:14: 49:28
+            debug self => _6;            // in scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+            scope 6 (inlined <std::ops::Range<usize> as iter::range::RangeIteratorImpl>::spec_next) { // at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                debug self => _6;        // in scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                let mut _7: &usize;      // in scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                let mut _8: &usize;      // in scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                let mut _9: bool;        // in scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                let _11: usize;          // in scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                let mut _12: usize;      // in scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                scope 7 {
+                    debug old => _11;    // in scope 7 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                    scope 8 {
+                    }
+                }
+            }
+        }
+    }
+    scope 4 (inlined <std::ops::Range<usize> as IntoIterator>::into_iter) { // at $DIR/slice_iter.rs:49:14: 49:28
+        debug self => _4;                // in scope 4 at $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
+    }
+
+    bb0: {
+        StorageLive(_3);                 // scope 0 at $DIR/slice_iter.rs:+1:17: +1:28
+        _3 = Len((*_1));                 // scope 0 at $DIR/slice_iter.rs:+1:17: +1:28
+        _4 = std::ops::Range::<usize> { start: const 0_usize, end: move _3 }; // scope 0 at $DIR/slice_iter.rs:+1:14: +1:28
+        StorageDead(_3);                 // scope 0 at $DIR/slice_iter.rs:+1:27: +1:28
+        StorageLive(_5);                 // scope 0 at $DIR/slice_iter.rs:+1:14: +1:28
+        _5 = move _4;                    // scope 0 at $DIR/slice_iter.rs:+1:14: +1:28
+        goto -> bb1;                     // scope 1 at $DIR/slice_iter.rs:+1:5: +4:6
+    }
+
+    bb1: {
+        StorageLive(_10);                // scope 1 at $DIR/slice_iter.rs:+1:14: +1:28
+        _6 = &mut _5;                    // scope 1 at $DIR/slice_iter.rs:+1:14: +1:28
+        StorageLive(_11);                // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_9);                 // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_7);                 // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _7 = &((*_6).0: usize);          // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_8);                 // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _8 = &((*_6).1: usize);          // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _9 = <usize as PartialOrd>::lt(move _7, move _8) -> [return: bb2, unwind: bb13]; // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: $SRC_DIR/core/src/iter/range.rs:LL:COL
+                                         // + literal: Const { ty: for<'a, 'b> fn(&'a usize, &'b usize) -> bool {<usize as PartialOrd>::lt}, val: Value(<ZST>) }
+    }
+
+    bb2: {
+        StorageDead(_8);                 // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageDead(_7);                 // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        switchInt(move _9) -> [0: bb3, otherwise: bb4]; // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+    }
+
+    bb3: {
+        _10 = Option::<usize>::None;     // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        goto -> bb6;                     // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+    }
+
+    bb4: {
+        _11 = ((*_6).0: usize);          // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageLive(_12);                // scope 7 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _12 = <usize as Step>::forward_unchecked(_11, const 1_usize) -> [return: bb5, unwind: bb13]; // scope 8 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: $SRC_DIR/core/src/iter/range.rs:LL:COL
+                                         // + literal: Const { ty: unsafe fn(usize, usize) -> usize {<usize as Step>::forward_unchecked}, val: Value(<ZST>) }
+    }
+
+    bb5: {
+        ((*_6).0: usize) = move _12;     // scope 7 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageDead(_12);                // scope 7 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _10 = Option::<usize>::Some(_11); // scope 7 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        goto -> bb6;                     // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+    }
+
+    bb6: {
+        StorageDead(_9);                 // scope 6 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        StorageDead(_11);                // scope 5 at $SRC_DIR/core/src/iter/range.rs:LL:COL
+        _13 = discriminant(_10);         // scope 1 at $DIR/slice_iter.rs:+1:14: +1:28
+        switchInt(move _13) -> [0: bb7, 1: bb9, otherwise: bb12]; // scope 1 at $DIR/slice_iter.rs:+1:14: +1:28
+    }
+
+    bb7: {
+        StorageDead(_10);                // scope 1 at $DIR/slice_iter.rs:+4:5: +4:6
+        StorageDead(_5);                 // scope 0 at $DIR/slice_iter.rs:+4:5: +4:6
+        drop(_2) -> bb8;                 // scope 0 at $DIR/slice_iter.rs:+5:1: +5:2
+    }
+
+    bb8: {
+        return;                          // scope 0 at $DIR/slice_iter.rs:+5:2: +5:2
+    }
+
+    bb9: {
+        _14 = ((_10 as Some).0: usize);  // scope 1 at $DIR/slice_iter.rs:+1:9: +1:10
+        _15 = Len((*_1));                // scope 2 at $DIR/slice_iter.rs:+2:18: +2:26
+        _16 = Lt(_14, _15);              // scope 2 at $DIR/slice_iter.rs:+2:18: +2:26
+        assert(move _16, "index out of bounds: the length is {} but the index is {}", move _15, _14) -> [success: bb10, unwind: bb13]; // scope 2 at $DIR/slice_iter.rs:+2:18: +2:26
+    }
+
+    bb10: {
+        _17 = &(*_1)[_14];               // scope 2 at $DIR/slice_iter.rs:+2:17: +2:26
+        StorageLive(_18);                // scope 3 at $DIR/slice_iter.rs:+3:9: +3:10
+        _18 = &_2;                       // scope 3 at $DIR/slice_iter.rs:+3:9: +3:10
+        StorageLive(_19);                // scope 3 at $DIR/slice_iter.rs:+3:9: +3:16
+        _19 = (_14, _17);                // scope 3 at $DIR/slice_iter.rs:+3:9: +3:16
+        _20 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _18, move _19) -> [return: bb11, unwind: bb13]; // scope 3 at $DIR/slice_iter.rs:+3:9: +3:16
+                                         // mir::Constant
+                                         // + span: $DIR/slice_iter.rs:51:9: 51:10
+                                         // + literal: Const { ty: for<'a> extern "rust-call" fn(&'a impl Fn(usize, &T), (usize, &T)) -> <impl Fn(usize, &T) as FnOnce<(usize, &T)>>::Output {<impl Fn(usize, &T) as Fn<(usize, &T)>>::call}, val: Value(<ZST>) }
+    }
+
+    bb11: {
+        StorageDead(_19);                // scope 3 at $DIR/slice_iter.rs:+3:15: +3:16
+        StorageDead(_18);                // scope 3 at $DIR/slice_iter.rs:+3:15: +3:16
+        StorageDead(_10);                // scope 1 at $DIR/slice_iter.rs:+4:5: +4:6
+        goto -> bb1;                     // scope 1 at $DIR/slice_iter.rs:+1:5: +4:6
+    }
+
+    bb12: {
+        unreachable;                     // scope 1 at $DIR/slice_iter.rs:+1:14: +1:28
+    }
+
+    bb13 (cleanup): {
+        drop(_2) -> [return: bb14, unwind terminate]; // scope 0 at $DIR/slice_iter.rs:+5:1: +5:2
+    }
+
+    bb14 (cleanup): {
+        resume;                          // scope 0 at $DIR/slice_iter.rs:+0:1: +5:2
+    }
+}
diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.mir
index 4fde50c6fe4..1aa05cbeb97 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.mir
@@ -44,21 +44,20 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                         scope 13 (inlined NonNull::<T>::new_unchecked) { // at $SRC_DIR/core/src/slice/iter.rs:LL:COL
                             debug ptr => _9; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
                             let mut _10: *const T; // in scope 13 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
-                            let mut _24: *mut T; // in scope 13 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                             scope 14 {
                                 scope 15 (inlined NonNull::<T>::new_unchecked::runtime::<T>) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
-                                    debug ptr => _24; // in scope 15 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                                    debug ptr => _9; // in scope 15 at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                                     scope 16 (inlined ptr::mut_ptr::<impl *mut T>::is_null) { // at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
-                                        debug self => _24; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                        let mut _25: *mut u8; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                        debug self => _9; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                        let mut _24: *mut u8; // in scope 16 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                         scope 17 {
                                             scope 18 (inlined ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                                debug ptr => _25; // in scope 18 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                debug ptr => _24; // in scope 18 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                                 scope 19 (inlined ptr::mut_ptr::<impl *mut u8>::addr) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                                    debug self => _25; // in scope 19 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                    debug self => _24; // in scope 19 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                                     scope 20 {
                                                         scope 21 (inlined ptr::mut_ptr::<impl *mut u8>::cast::<()>) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-                                                            debug self => _25; // in scope 21 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+                                                            debug self => _24; // in scope 21 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
                                                         }
                                                     }
                                                 }
@@ -134,10 +133,8 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
         _9 = _4 as *mut T (PtrToPtr);    // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
         StorageLive(_10);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
         StorageLive(_24);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
-        StorageLive(_25);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
         _10 = _9 as *const T (Pointer(MutToConstPointer)); // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
         _11 = NonNull::<T> { pointer: _10 }; // scope 14 at $SRC_DIR/core/src/ptr/non_null.rs:LL:COL
-        StorageDead(_25);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
         StorageDead(_24);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
         StorageDead(_10);                // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
         StorageDead(_9);                 // scope 7 at $SRC_DIR/core/src/slice/iter.rs:LL:COL
diff --git a/tests/mir-opt/pre-codegen/slice_iter.rs b/tests/mir-opt/pre-codegen/slice_iter.rs
index ca423ca55e6..a1cd85e753f 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.rs
+++ b/tests/mir-opt/pre-codegen/slice_iter.rs
@@ -36,3 +36,18 @@ pub fn reverse_loop<'a, T>(slice: &'a [T], f: impl Fn(&T)) {
         f(x)
     }
 }
+
+// EMIT_MIR slice_iter.enumerated_loop.PreCodegen.after.mir
+pub fn enumerated_loop<'a, T>(slice: &'a [T], f: impl Fn(usize, &T)) {
+    for (i, x) in slice.iter().enumerate() {
+        f(i, x)
+    }
+}
+
+// EMIT_MIR slice_iter.range_loop.PreCodegen.after.mir
+pub fn range_loop<'a, T>(slice: &'a [T], f: impl Fn(usize, &T)) {
+    for i in 0..slice.len() {
+        let x = &slice[i];
+        f(i, x)
+    }
+}
diff --git a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
index bdf1de468b3..7f0e50a23f9 100644
--- a/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
+++ b/tests/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
@@ -9,70 +9,61 @@
       let mut _4: std::result::Result<i32, i32>; // in scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9
       let mut _5: isize;                   // in scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
       let _6: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
-      let mut _7: !;                       // in scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
-      let mut _8: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
-      let _9: i32;                         // in scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+      let mut _7: std::result::Result<std::convert::Infallible, i32>; // in scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
+      let _8: i32;                         // in scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
       scope 1 {
           debug residual => _6;            // in scope 1 at $DIR/separate_const_switch.rs:+1:9: +1:10
           scope 2 {
               scope 8 (inlined #[track_caller] <Result<i32, i32> as FromResidual<Result<Infallible, i32>>>::from_residual) { // at $DIR/separate_const_switch.rs:25:8: 25:10
-                  debug residual => _8;    // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
-                  let _14: i32;            // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
-                  let mut _15: i32;        // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+                  debug residual => _6;    // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+                  let _13: i32;            // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+                  let mut _14: i32;        // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
                   scope 9 {
-                      debug e => _14;      // in scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
+                      debug e => _13;      // in scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
                       scope 10 (inlined <i32 as From<i32>>::from) { // at $SRC_DIR/core/src/result.rs:LL:COL
-                          debug t => _14;  // in scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                          debug t => _13;  // in scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
                       }
                   }
               }
           }
       }
       scope 3 {
-          debug val => _9;                 // in scope 3 at $DIR/separate_const_switch.rs:+1:8: +1:10
+          debug val => _8;                 // in scope 3 at $DIR/separate_const_switch.rs:+1:8: +1:10
           scope 4 {
           }
       }
       scope 5 (inlined <Result<i32, i32> as Try>::branch) { // at $DIR/separate_const_switch.rs:25:8: 25:10
-          debug self => _4;                // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-          let mut _10: isize;              // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+          debug self => _1;                // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+          let mut _9: isize;               // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+          let _10: i32;                    // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
           let _11: i32;                    // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-          let _12: i32;                    // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-          let mut _13: std::result::Result<std::convert::Infallible, i32>; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+          let mut _12: std::result::Result<std::convert::Infallible, i32>; // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
           scope 6 {
-              debug v => _11;              // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+              debug v => _10;              // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
           }
           scope 7 {
-              debug e => _12;              // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+              debug e => _11;              // in scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
           }
       }
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
           StorageLive(_3);                 // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-          StorageLive(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9
-          _4 = _1;                         // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9
+          StorageLive(_10);                // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
           StorageLive(_11);                // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-          StorageLive(_12);                // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-          _10 = discriminant(_4);          // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-          switchInt(move _10) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+          _9 = discriminant(_1);           // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+          switchInt(move _9) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
       }
   
       bb1: {
-          StorageDead(_12);                // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
           StorageDead(_11);                // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-          StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
+          StorageDead(_10);                // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
           _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
           switchInt(move _5) -> [0: bb2, 1: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
       }
   
       bb2: {
-          StorageLive(_9);                 // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-          _9 = ((_3 as Continue).0: i32);  // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-          _2 = _9;                         // scope 4 at $DIR/separate_const_switch.rs:+1:8: +1:10
-          StorageDead(_9);                 // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
-          _0 = Result::<i32, i32>::Ok(move _2); // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11
-          StorageDead(_2);                 // scope 0 at $DIR/separate_const_switch.rs:+1:10: +1:11
+          _8 = ((_3 as Continue).0: i32);  // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+          _0 = Result::<i32, i32>::Ok(_8); // scope 0 at $DIR/separate_const_switch.rs:+1:5: +1:11
           StorageDead(_3);                 // scope 0 at $DIR/separate_const_switch.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2
       }
@@ -82,30 +73,19 @@
       }
   
       bb4: {
-          StorageLive(_6);                 // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
           _6 = ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
-          StorageLive(_8);                 // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10
-          _8 = _6;                         // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10
-          StorageLive(_14);                // scope 2 at $DIR/separate_const_switch.rs:+1:8: +1:10
-          _14 = move ((_8 as Err).0: i32); // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
-          StorageLive(_15);                // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
-          _15 = move _14;                  // scope 10 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
-          _0 = Result::<i32, i32>::Err(move _15); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
-          StorageDead(_15);                // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
-          StorageDead(_14);                // scope 2 at $DIR/separate_const_switch.rs:+1:8: +1:10
-          StorageDead(_8);                 // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10
-          StorageDead(_6);                 // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
-          StorageDead(_2);                 // scope 0 at $DIR/separate_const_switch.rs:+1:10: +1:11
+          _13 = ((_6 as Err).0: i32);      // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+          _0 = Result::<i32, i32>::Err(move _13); // scope 9 at $SRC_DIR/core/src/result.rs:LL:COL
           StorageDead(_3);                 // scope 0 at $DIR/separate_const_switch.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2
       }
   
       bb5: {
-          _12 = move ((_4 as Err).0: i32); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-          StorageLive(_13);                // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-          _13 = Result::<Infallible, i32>::Err(move _12); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-          _3 = ControlFlow::<Result<Infallible, i32>, i32>::Break(move _13); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
-          StorageDead(_13);                // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+          _11 = ((_1 as Err).0: i32);      // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+          StorageLive(_12);                // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+          _12 = Result::<Infallible, i32>::Err(move _11); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+          _3 = ControlFlow::<Result<Infallible, i32>, i32>::Break(move _12); // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
+          StorageDead(_12);                // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
           goto -> bb1;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
       }
   
@@ -114,8 +94,8 @@
       }
   
       bb7: {
-          _11 = move ((_4 as Ok).0: i32);  // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-          _3 = ControlFlow::<Result<Infallible, i32>, i32>::Continue(move _11); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+          _10 = ((_1 as Ok).0: i32);       // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+          _3 = ControlFlow::<Result<Infallible, i32>, i32>::Continue(move _10); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
           goto -> bb1;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
       }
   }
diff --git a/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff b/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff
index b5e0a66d83f..f86a96dec41 100644
--- a/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff
+++ b/tests/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff
@@ -34,13 +34,8 @@
       }
   
       bb1: {
-          StorageLive(_6);                 // scope 0 at $DIR/separate_const_switch.rs:+8:17: +8:18
           _6 = ((_1 as Err).0: usize);     // scope 0 at $DIR/separate_const_switch.rs:+8:17: +8:18
-          StorageLive(_7);                 // scope 2 at $DIR/separate_const_switch.rs:+8:42: +8:43
-          _7 = _6;                         // scope 2 at $DIR/separate_const_switch.rs:+8:42: +8:43
-          _2 = ControlFlow::<usize, i32>::Break(move _7); // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44
-          StorageDead(_7);                 // scope 2 at $DIR/separate_const_switch.rs:+8:43: +8:44
-          StorageDead(_6);                 // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44
+          _2 = ControlFlow::<usize, i32>::Break(_6); // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44
           goto -> bb4;                     // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44
       }
   
@@ -49,13 +44,8 @@
       }
   
       bb3: {
-          StorageLive(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+7:16: +7:17
           _4 = ((_1 as Ok).0: i32);        // scope 0 at $DIR/separate_const_switch.rs:+7:16: +7:17
-          StorageLive(_5);                 // scope 1 at $DIR/separate_const_switch.rs:+7:44: +7:45
-          _5 = _4;                         // scope 1 at $DIR/separate_const_switch.rs:+7:44: +7:45
-          _2 = ControlFlow::<usize, i32>::Continue(move _5); // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46
-          StorageDead(_5);                 // scope 1 at $DIR/separate_const_switch.rs:+7:45: +7:46
-          StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+7:45: +7:46
+          _2 = ControlFlow::<usize, i32>::Continue(_4); // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46
           goto -> bb4;                     // scope 0 at $DIR/separate_const_switch.rs:+7:45: +7:46
       }
   
@@ -73,13 +63,8 @@
       }
   
       bb6: {
-          StorageLive(_9);                 // scope 0 at $DIR/separate_const_switch.rs:+11:31: +11:32
           _9 = ((_2 as Continue).0: i32);  // scope 0 at $DIR/separate_const_switch.rs:+11:31: +11:32
-          StorageLive(_10);                // scope 3 at $DIR/separate_const_switch.rs:+11:42: +11:43
-          _10 = _9;                        // scope 3 at $DIR/separate_const_switch.rs:+11:42: +11:43
-          _0 = Option::<i32>::Some(move _10); // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44
-          StorageDead(_10);                // scope 3 at $DIR/separate_const_switch.rs:+11:43: +11:44
-          StorageDead(_9);                 // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
+          _0 = Option::<i32>::Some(_9);    // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44
           goto -> bb7;                     // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
       }
   
diff --git a/tests/mir-opt/slice_filter.rs b/tests/mir-opt/slice_filter.rs
deleted file mode 100644
index be32f40f132..00000000000
--- a/tests/mir-opt/slice_filter.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-fn main() {
-    let input = vec![];
-    let _variant_a_result = variant_a(&input);
-    let _variant_b_result = variant_b(&input);
-}
-
-pub fn variant_a(input: &[(usize, usize, usize, usize)]) -> usize {
-    input.iter().filter(|(a, b, c, d)| a <= c && d <= b || c <= a && b <= d).count()
-}
-
-pub fn variant_b(input: &[(usize, usize, usize, usize)]) -> usize {
-    input.iter().filter(|&&(a, b, c, d)| a <= c && d <= b || c <= a && b <= d).count()
-}
-
-// EMIT_MIR slice_filter.variant_a-{closure#0}.ReferencePropagation.diff
-// EMIT_MIR slice_filter.variant_a-{closure#0}.CopyProp.diff
-// EMIT_MIR slice_filter.variant_a-{closure#0}.DestinationPropagation.diff
-// EMIT_MIR slice_filter.variant_b-{closure#0}.CopyProp.diff
-// EMIT_MIR slice_filter.variant_b-{closure#0}.ReferencePropagation.diff
-// EMIT_MIR slice_filter.variant_b-{closure#0}.DestinationPropagation.diff
diff --git a/tests/mir-opt/slice_filter.variant_a-{closure#0}.CopyProp.diff b/tests/mir-opt/slice_filter.variant_a-{closure#0}.CopyProp.diff
deleted file mode 100644
index 60e5056c7a9..00000000000
--- a/tests/mir-opt/slice_filter.variant_a-{closure#0}.CopyProp.diff
+++ /dev/null
@@ -1,279 +0,0 @@
-- // MIR for `variant_a::{closure#0}` before CopyProp
-+ // MIR for `variant_a::{closure#0}` after CopyProp
-  
-  fn variant_a::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:8:25: 8:39], _2: &&(usize, usize, usize, usize)) -> bool {
-      let mut _0: bool;                    // return place in scope 0 at $DIR/slice_filter.rs:+0:40: +0:40
-      let _3: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-      let _4: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-      let _5: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-      let _6: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
-      let mut _7: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:56
-      let mut _8: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:46
-      let mut _9: &&usize;                 // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:41
-      let mut _10: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:45: +0:46
-      let _11: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:45: +0:46
-      let mut _12: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:50: +0:56
-      let mut _13: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:50: +0:51
-      let mut _14: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:55: +0:56
-      let _15: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:55: +0:56
-      let mut _16: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:76
-      let mut _17: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:66
-      let mut _18: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:61
-      let mut _19: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:65: +0:66
-      let _20: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:65: +0:66
-      let mut _21: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:70: +0:76
-      let mut _22: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:70: +0:71
-      let mut _23: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-      let _24: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-      let mut _25: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
-      let mut _26: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
-      let mut _27: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
-      let mut _28: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
-      let mut _31: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
-      let mut _32: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
-      let mut _37: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
-      let mut _38: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
-      let mut _43: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
-      let mut _44: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
-      let mut _49: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
-      let mut _50: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
-      scope 1 {
-          debug a => _3;                   // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
-          debug b => _4;                   // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
-          debug c => _5;                   // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
-          debug d => _6;                   // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
-          scope 2 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:40: 8:46
-              debug self => _9;            // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => _10;          // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _29: &usize;         // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _30: &usize;         // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              scope 3 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
--                 debug self => _31;       // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
--                 debug other => _32;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+                 debug self => _29;       // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+                 debug other => _30;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _33: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _34: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              }
-          }
-          scope 4 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:60: 8:66
-              debug self => _18;           // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => _19;          // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _35: &usize;         // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _36: &usize;         // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              scope 5 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
--                 debug self => _37;       // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
--                 debug other => _38;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+                 debug self => _35;       // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+                 debug other => _36;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _39: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _40: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              }
-          }
-          scope 6 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:50: 8:56
-              debug self => _13;           // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => _14;          // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _41: &usize;         // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _42: &usize;         // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              scope 7 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
--                 debug self => _43;       // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
--                 debug other => _44;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+                 debug self => _41;       // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+                 debug other => _42;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _45: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _46: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              }
-          }
-          scope 8 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:70: 8:76
-              debug self => _22;           // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => _23;          // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _47: &usize;         // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _48: &usize;         // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              scope 9 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
--                 debug self => _49;       // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
--                 debug other => _50;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+                 debug self => _47;       // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+                 debug other => _48;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _51: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _52: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              }
-          }
-      }
-  
-      bb0: {
-          StorageLive(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-          _25 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-          _3 = &((*_25).0: usize);         // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-          StorageLive(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-          _26 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-          _4 = &((*_26).1: usize);         // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-          StorageLive(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-          _27 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-          _5 = &((*_27).2: usize);         // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-          StorageLive(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
-          _28 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
-          _6 = &((*_28).3: usize);         // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
-          StorageLive(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
-          StorageLive(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:46
-          StorageLive(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
-          _9 = &_3;                        // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
-          StorageLive(_10);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          StorageLive(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          _11 = _5;                        // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          _10 = &_11;                      // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          _29 = deref_copy (*_9);          // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _30 = deref_copy (*_10);         // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageLive(_31);                // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _31 = _29;                       // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageLive(_32);                // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _32 = _30;                       // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_33);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _33 = (*_31);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _33 = (*_29);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_34);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _34 = (*_32);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _34 = (*_30);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _8 = Le(move _33, move _34);     // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_34);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_33);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageDead(_32);                // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageDead(_31);                // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          StorageDead(_10);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          StorageDead(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          switchInt(move _8) -> [0: bb4, otherwise: bb5]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
-      }
-  
-      bb1: {
-          _0 = const true;                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
-          goto -> bb3;                     // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
-      }
-  
-      bb2: {
-          StorageLive(_16);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-          StorageLive(_17);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:66
-          StorageLive(_18);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
-          _18 = &_5;                       // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
-          StorageLive(_19);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          StorageLive(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          _20 = _3;                        // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          _19 = &_20;                      // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          _35 = deref_copy (*_18);         // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _36 = deref_copy (*_19);         // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageLive(_37);                // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _37 = _35;                       // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageLive(_38);                // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _38 = _36;                       // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_39);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _39 = (*_37);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _39 = (*_35);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_40);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _40 = (*_38);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _40 = (*_36);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _17 = Le(move _39, move _40);    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_40);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_39);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageDead(_38);                // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageDead(_37);                // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          StorageDead(_19);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          StorageDead(_18);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          switchInt(move _17) -> [0: bb6, otherwise: bb7]; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-      }
-  
-      bb3: {
-          StorageDead(_16);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-          return;                          // scope 0 at $DIR/slice_filter.rs:+0:76: +0:76
-      }
-  
-      bb4: {
-          _7 = const false;                // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
-          StorageDead(_12);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          goto -> bb2;                     // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
-      }
-  
-      bb5: {
-          StorageLive(_12);                // scope 1 at $DIR/slice_filter.rs:+0:50: +0:56
-          StorageLive(_13);                // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
-          _13 = &_6;                       // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
-          StorageLive(_14);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageLive(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          _15 = _4;                        // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          _14 = &_15;                      // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          _41 = deref_copy (*_13);         // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _42 = deref_copy (*_14);         // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageLive(_43);                // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _43 = _41;                       // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageLive(_44);                // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _44 = _42;                       // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_45);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _45 = (*_43);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _45 = (*_41);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_46);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _46 = (*_44);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _46 = (*_42);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _12 = Le(move _45, move _46);    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_46);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_45);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageDead(_44);                // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageDead(_43);                // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageDead(_14);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageDead(_13);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          _7 = move _12;                   // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
-          StorageDead(_12);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          switchInt(move _7) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
-      }
-  
-      bb6: {
-          _16 = const false;               // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-          goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-      }
-  
-      bb7: {
-          StorageLive(_21);                // scope 1 at $DIR/slice_filter.rs:+0:70: +0:76
-          StorageLive(_22);                // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
-          _22 = &_4;                       // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
-          StorageLive(_23);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageLive(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          _24 = _6;                        // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          _23 = &_24;                      // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          _47 = deref_copy (*_22);         // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _48 = deref_copy (*_23);         // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageLive(_49);                // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _49 = _47;                       // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageLive(_50);                // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _50 = _48;                       // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_51);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _51 = (*_49);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _51 = (*_47);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_52);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _52 = (*_50);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _52 = (*_48);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _21 = Le(move _51, move _52);    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_52);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_51);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageDead(_50);                // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageDead(_49);                // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_23);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_22);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          _16 = move _21;                  // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-          goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-      }
-  
-      bb8: {
-          StorageDead(_21);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_17);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          _0 = move _16;                   // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
-          goto -> bb3;                     // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
-      }
-  }
-  
diff --git a/tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff b/tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff
deleted file mode 100644
index afdcf57815f..00000000000
--- a/tests/mir-opt/slice_filter.variant_a-{closure#0}.DestinationPropagation.diff
+++ /dev/null
@@ -1,165 +0,0 @@
-- // MIR for `variant_a::{closure#0}` before DestinationPropagation
-+ // MIR for `variant_a::{closure#0}` after DestinationPropagation
-  
-  fn variant_a::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:8:25: 8:39], _2: &&(usize, usize, usize, usize)) -> bool {
-      let mut _0: bool;                    // return place in scope 0 at $DIR/slice_filter.rs:+0:40: +0:40
-      let mut _3: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:56
-      let mut _4: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:46
-      let mut _5: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:50: +0:56
-      let mut _6: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:76
-      let mut _7: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:66
-      let mut _8: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:70: +0:76
-      let mut _9: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
-      let mut _10: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
-      let mut _11: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
-      let mut _12: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
-      scope 1 {
-          debug a => &((*_9).0: usize);    // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
-          debug b => &((*_10).1: usize);   // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
-          debug c => &((*_11).2: usize);   // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
-          debug d => &((*_12).3: usize);   // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
-          scope 2 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:40: 8:46
-              debug self => &&((*_9).0: usize); // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => &&((*_11).2: usize); // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              scope 3 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug self => &((*_9).0: usize); // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug other => &((*_11).2: usize); // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _13: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _14: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              }
-          }
-          scope 4 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:60: 8:66
-              debug self => &&((*_11).2: usize); // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => &&((*_9).0: usize); // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              scope 5 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug self => &((*_11).2: usize); // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug other => &((*_9).0: usize); // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _15: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _16: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              }
-          }
-          scope 6 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:50: 8:56
-              debug self => &&((*_12).3: usize); // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => &&((*_10).1: usize); // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              scope 7 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug self => &((*_12).3: usize); // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug other => &((*_10).1: usize); // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _17: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _18: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              }
-          }
-          scope 8 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:70: 8:76
-              debug self => &&((*_10).1: usize); // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              debug other => &&((*_12).3: usize); // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              scope 9 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug self => &((*_10).1: usize); // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  debug other => &((*_12).3: usize); // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _19: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _20: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              }
-          }
-      }
-  
-      bb0: {
-          _9 = deref_copy (*_2);           // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-          _10 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-          _11 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-          _12 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
--         StorageLive(_3);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
-          StorageLive(_4);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:46
-          StorageLive(_13);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _13 = ((*_9).0: usize);          // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_14);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _14 = ((*_11).2: usize);         // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _4 = Le(move _13, move _14);     // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_14);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_13);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          switchInt(move _4) -> [0: bb4, otherwise: bb5]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
-      }
-  
-      bb1: {
-          _0 = const true;                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
-          goto -> bb3;                     // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
-      }
-  
-      bb2: {
--         StorageLive(_6);                 // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-          StorageLive(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:60: +0:66
-          StorageLive(_15);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _15 = ((*_11).2: usize);         // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_16);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _16 = ((*_9).0: usize);          // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _7 = Le(move _15, move _16);     // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_16);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_15);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          switchInt(move _7) -> [0: bb6, otherwise: bb7]; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-      }
-  
-      bb3: {
--         StorageDead(_6);                 // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         StorageDead(_3);                 // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          return;                          // scope 0 at $DIR/slice_filter.rs:+0:76: +0:76
-      }
-  
-      bb4: {
--         StorageDead(_5);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageDead(_4);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          goto -> bb2;                     // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
-      }
-  
-      bb5: {
--         StorageLive(_5);                 // scope 1 at $DIR/slice_filter.rs:+0:50: +0:56
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:50: +0:56
-          StorageLive(_17);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _17 = ((*_12).3: usize);         // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_18);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _18 = ((*_10).1: usize);         // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _5 = Le(move _17, move _18);     // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_18);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_17);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _3 = move _5;                    // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
--         StorageDead(_5);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageDead(_4);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
--         switchInt(move _3) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
-+         switchInt(move _5) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
-      }
-  
-      bb6: {
--         _6 = const false;                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-+         _0 = const false;                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-          goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-      }
-  
-      bb7: {
--         StorageLive(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:70: +0:76
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:70: +0:76
-          StorageLive(_19);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _19 = ((*_10).1: usize);         // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_20);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _20 = ((*_12).3: usize);         // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _8 = Le(move _19, move _20);     // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _0 = Le(move _19, move _20);     // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_20);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_19);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _6 = move _8;                    // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-          goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-      }
-  
-      bb8: {
--         StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         _0 = move _6;                    // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
-          goto -> bb3;                     // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
-      }
-  }
-  
diff --git a/tests/mir-opt/slice_filter.variant_a-{closure#0}.ReferencePropagation.diff b/tests/mir-opt/slice_filter.variant_a-{closure#0}.ReferencePropagation.diff
deleted file mode 100644
index 2534eeef432..00000000000
--- a/tests/mir-opt/slice_filter.variant_a-{closure#0}.ReferencePropagation.diff
+++ /dev/null
@@ -1,267 +0,0 @@
-- // MIR for `variant_a::{closure#0}` before ReferencePropagation
-+ // MIR for `variant_a::{closure#0}` after ReferencePropagation
-  
-  fn variant_a::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:8:25: 8:39], _2: &&(usize, usize, usize, usize)) -> bool {
-      let mut _0: bool;                    // return place in scope 0 at $DIR/slice_filter.rs:+0:40: +0:40
-      let _3: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-      let _4: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-      let _5: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-      let _6: &usize;                      // in scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
-      let mut _7: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:56
-      let mut _8: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:46
-      let mut _9: &&usize;                 // in scope 0 at $DIR/slice_filter.rs:+0:40: +0:41
-      let mut _10: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:45: +0:46
-      let _11: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:45: +0:46
-      let mut _12: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:50: +0:56
-      let mut _13: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:50: +0:51
-      let mut _14: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:55: +0:56
-      let _15: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:55: +0:56
-      let mut _16: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:76
-      let mut _17: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:66
-      let mut _18: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:60: +0:61
-      let mut _19: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:65: +0:66
-      let _20: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:65: +0:66
-      let mut _21: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:70: +0:76
-      let mut _22: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:70: +0:71
-      let mut _23: &&usize;                // in scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-      let _24: &usize;                     // in scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-      let mut _25: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
-      let mut _26: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
-      let mut _27: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
-      let mut _28: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:38
-      let mut _31: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
-      let mut _32: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
-      let mut _37: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
-      let mut _38: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
-      let mut _43: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
-      let mut _44: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
-      let mut _49: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
-      let mut _50: &usize;                 // in scope 0 at $SRC_DIR/core/src/cmp.rs:LL:COL
-      scope 1 {
--         debug a => _3;                   // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
--         debug b => _4;                   // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
--         debug c => _5;                   // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
--         debug d => _6;                   // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
-+         debug a => &((*_25).0: usize);   // in scope 1 at $DIR/slice_filter.rs:+0:27: +0:28
-+         debug b => &((*_26).1: usize);   // in scope 1 at $DIR/slice_filter.rs:+0:30: +0:31
-+         debug c => &((*_27).2: usize);   // in scope 1 at $DIR/slice_filter.rs:+0:33: +0:34
-+         debug d => &((*_28).3: usize);   // in scope 1 at $DIR/slice_filter.rs:+0:36: +0:37
-          scope 2 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:40: 8:46
--             debug self => _9;            // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
--             debug other => _10;          // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+             debug self => &&((*_25).0: usize); // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+             debug other => &&((*_27).2: usize); // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _29: &usize;         // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _30: &usize;         // in scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              scope 3 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
--                 debug self => _29;       // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
--                 debug other => _30;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+                 debug self => &((*_25).0: usize); // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+                 debug other => &((*_27).2: usize); // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _33: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _34: usize;      // in scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              }
-          }
-          scope 4 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:60: 8:66
--             debug self => _18;           // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
--             debug other => _19;          // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+             debug self => &&((*_27).2: usize); // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+             debug other => &&((*_25).0: usize); // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _35: &usize;         // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _36: &usize;         // in scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              scope 5 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
--                 debug self => _35;       // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
--                 debug other => _36;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+                 debug self => &((*_27).2: usize); // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+                 debug other => &((*_25).0: usize); // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _39: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _40: usize;      // in scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              }
-          }
-          scope 6 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:50: 8:56
--             debug self => _13;           // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
--             debug other => _14;          // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+             debug self => &&((*_28).3: usize); // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+             debug other => &&((*_26).1: usize); // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _41: &usize;         // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _42: &usize;         // in scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              scope 7 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
--                 debug self => _41;       // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
--                 debug other => _42;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+                 debug self => &((*_28).3: usize); // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+                 debug other => &((*_26).1: usize); // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _45: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _46: usize;      // in scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              }
-          }
-          scope 8 (inlined cmp::impls::<impl PartialOrd for &usize>::le) { // at $DIR/slice_filter.rs:8:70: 8:76
--             debug self => _22;           // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
--             debug other => _23;          // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+             debug self => &&((*_26).1: usize); // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+             debug other => &&((*_28).3: usize); // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _47: &usize;         // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              let mut _48: &usize;         // in scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              scope 9 (inlined cmp::impls::<impl PartialOrd for usize>::le) { // at $SRC_DIR/core/src/cmp.rs:LL:COL
--                 debug self => _47;       // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
--                 debug other => _48;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+                 debug self => &((*_26).1: usize); // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+                 debug other => &((*_28).3: usize); // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _51: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-                  let mut _52: usize;      // in scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-              }
-          }
-      }
-  
-      bb0: {
--         StorageLive(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
-          _25 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
--         _3 = &((*_25).0: usize);         // scope 0 at $DIR/slice_filter.rs:+0:27: +0:28
--         StorageLive(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
-          _26 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
--         _4 = &((*_26).1: usize);         // scope 0 at $DIR/slice_filter.rs:+0:30: +0:31
--         StorageLive(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
-          _27 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
--         _5 = &((*_27).2: usize);         // scope 0 at $DIR/slice_filter.rs:+0:33: +0:34
--         StorageLive(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
-          _28 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
--         _6 = &((*_28).3: usize);         // scope 0 at $DIR/slice_filter.rs:+0:36: +0:37
-          StorageLive(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
-          StorageLive(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:46
--         StorageLive(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
--         _9 = &_3;                        // scope 1 at $DIR/slice_filter.rs:+0:40: +0:41
--         StorageLive(_10);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
--         StorageLive(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
--         _11 = _5;                        // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
--         _10 = &_11;                      // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
--         _29 = deref_copy (*_9);          // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _30 = deref_copy (*_10);         // scope 2 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_33);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _33 = (*_29);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _33 = ((*_25).0: usize);         // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_34);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _34 = (*_30);                    // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _34 = ((*_27).2: usize);         // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _8 = Le(move _33, move _34);     // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_34);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_33);                // scope 3 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageDead(_11);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
--         StorageDead(_10);                // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
--         StorageDead(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:45: +0:46
-          switchInt(move _8) -> [0: bb4, otherwise: bb5]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
-      }
-  
-      bb1: {
-          _0 = const true;                 // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
-          goto -> bb3;                     // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
-      }
-  
-      bb2: {
-          StorageLive(_16);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-          StorageLive(_17);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:66
--         StorageLive(_18);                // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
--         _18 = &_5;                       // scope 1 at $DIR/slice_filter.rs:+0:60: +0:61
--         StorageLive(_19);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
--         StorageLive(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
--         _20 = _3;                        // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
--         _19 = &_20;                      // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
--         _35 = deref_copy (*_18);         // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _36 = deref_copy (*_19);         // scope 4 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_39);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _39 = (*_35);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _39 = ((*_27).2: usize);         // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_40);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _40 = (*_36);                    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _40 = ((*_25).0: usize);         // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _17 = Le(move _39, move _40);    // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_40);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_39);                // scope 5 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageDead(_20);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
--         StorageDead(_19);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
--         StorageDead(_18);                // scope 1 at $DIR/slice_filter.rs:+0:65: +0:66
-          switchInt(move _17) -> [0: bb6, otherwise: bb7]; // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-      }
-  
-      bb3: {
-          StorageDead(_16);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         StorageDead(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
--         StorageDead(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
--         StorageDead(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
--         StorageDead(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:75: +0:76
-          return;                          // scope 0 at $DIR/slice_filter.rs:+0:76: +0:76
-      }
-  
-      bb4: {
-          _7 = const false;                // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
-          StorageDead(_12);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          goto -> bb2;                     // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
-      }
-  
-      bb5: {
-          StorageLive(_12);                // scope 1 at $DIR/slice_filter.rs:+0:50: +0:56
--         StorageLive(_13);                // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
--         _13 = &_6;                       // scope 1 at $DIR/slice_filter.rs:+0:50: +0:51
--         StorageLive(_14);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
--         StorageLive(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
--         _15 = _4;                        // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
--         _14 = &_15;                      // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
--         _41 = deref_copy (*_13);         // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _42 = deref_copy (*_14);         // scope 6 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_45);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _45 = (*_41);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _45 = ((*_28).3: usize);         // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_46);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _46 = (*_42);                    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _46 = ((*_26).1: usize);         // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _12 = Le(move _45, move _46);    // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_46);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_45);                // scope 7 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageDead(_15);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
--         StorageDead(_14);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
--         StorageDead(_13);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          _7 = move _12;                   // scope 1 at $DIR/slice_filter.rs:+0:40: +0:56
-          StorageDead(_12);                // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:55: +0:56
-          switchInt(move _7) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
-      }
-  
-      bb6: {
-          _16 = const false;               // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-          goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-      }
-  
-      bb7: {
-          StorageLive(_21);                // scope 1 at $DIR/slice_filter.rs:+0:70: +0:76
--         StorageLive(_22);                // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
--         _22 = &_4;                       // scope 1 at $DIR/slice_filter.rs:+0:70: +0:71
--         StorageLive(_23);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         StorageLive(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         _24 = _6;                        // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         _23 = &_24;                      // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         _47 = deref_copy (*_22);         // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _48 = deref_copy (*_23);         // scope 8 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_51);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _51 = (*_47);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _51 = ((*_26).1: usize);         // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageLive(_52);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         _52 = (*_48);                    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-+         _52 = ((*_28).3: usize);         // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          _21 = Le(move _51, move _52);    // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_52);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
-          StorageDead(_51);                // scope 9 at $SRC_DIR/core/src/cmp.rs:LL:COL
--         StorageDead(_24);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         StorageDead(_23);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
--         StorageDead(_22);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          _16 = move _21;                  // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-          goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:60: +0:76
-      }
-  
-      bb8: {
-          StorageDead(_21);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          StorageDead(_17);                // scope 1 at $DIR/slice_filter.rs:+0:75: +0:76
-          _0 = move _16;                   // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
-          goto -> bb3;                     // scope 1 at $DIR/slice_filter.rs:+0:40: +0:76
-      }
-  }
-  
diff --git a/tests/mir-opt/slice_filter.variant_b-{closure#0}.CopyProp.diff b/tests/mir-opt/slice_filter.variant_b-{closure#0}.CopyProp.diff
deleted file mode 100644
index 5e4bdbdfa2e..00000000000
--- a/tests/mir-opt/slice_filter.variant_b-{closure#0}.CopyProp.diff
+++ /dev/null
@@ -1,139 +0,0 @@
-- // MIR for `variant_b::{closure#0}` before CopyProp
-+ // MIR for `variant_b::{closure#0}` after CopyProp
-  
-  fn variant_b::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:12:25: 12:41], _2: &&(usize, usize, usize, usize)) -> bool {
-      let mut _0: bool;                    // return place in scope 0 at $DIR/slice_filter.rs:+0:42: +0:42
-      let _3: usize;                       // in scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
-      let _4: usize;                       // in scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
-      let _5: usize;                       // in scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
-      let _6: usize;                       // in scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
-      let mut _7: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:42: +0:58
-      let mut _8: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:42: +0:48
-      let mut _9: usize;                   // in scope 0 at $DIR/slice_filter.rs:+0:42: +0:43
-      let mut _10: usize;                  // in scope 0 at $DIR/slice_filter.rs:+0:47: +0:48
-      let mut _11: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:52: +0:58
-      let mut _12: usize;                  // in scope 0 at $DIR/slice_filter.rs:+0:52: +0:53
-      let mut _13: usize;                  // in scope 0 at $DIR/slice_filter.rs:+0:57: +0:58
-      let mut _14: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:62: +0:78
-      let mut _15: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:62: +0:68
-      let mut _16: usize;                  // in scope 0 at $DIR/slice_filter.rs:+0:62: +0:63
-      let mut _17: usize;                  // in scope 0 at $DIR/slice_filter.rs:+0:67: +0:68
-      let mut _18: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:72: +0:78
-      let mut _19: usize;                  // in scope 0 at $DIR/slice_filter.rs:+0:72: +0:73
-      let mut _20: usize;                  // in scope 0 at $DIR/slice_filter.rs:+0:77: +0:78
-      let mut _21: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
-      let mut _22: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
-      let mut _23: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
-      let mut _24: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
-      scope 1 {
-          debug a => _3;                   // in scope 1 at $DIR/slice_filter.rs:+0:29: +0:30
-          debug b => _4;                   // in scope 1 at $DIR/slice_filter.rs:+0:32: +0:33
-          debug c => _5;                   // in scope 1 at $DIR/slice_filter.rs:+0:35: +0:36
-          debug d => _6;                   // in scope 1 at $DIR/slice_filter.rs:+0:38: +0:39
-      }
-  
-      bb0: {
--         StorageLive(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
-          _21 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
-          _3 = ((*_21).0: usize);          // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
--         StorageLive(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
-          _22 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
-          _4 = ((*_22).1: usize);          // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
--         StorageLive(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
-          _23 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
-          _5 = ((*_23).2: usize);          // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
--         StorageLive(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
-          _24 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
-          _6 = ((*_24).3: usize);          // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
-          StorageLive(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
-          StorageLive(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:42: +0:48
--         StorageLive(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:42: +0:43
--         _9 = _3;                         // scope 1 at $DIR/slice_filter.rs:+0:42: +0:43
--         StorageLive(_10);                // scope 1 at $DIR/slice_filter.rs:+0:47: +0:48
--         _10 = _5;                        // scope 1 at $DIR/slice_filter.rs:+0:47: +0:48
--         _8 = Le(move _9, move _10);      // scope 1 at $DIR/slice_filter.rs:+0:42: +0:48
--         StorageDead(_10);                // scope 1 at $DIR/slice_filter.rs:+0:47: +0:48
--         StorageDead(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:47: +0:48
-+         _8 = Le(_3, _5);                 // scope 1 at $DIR/slice_filter.rs:+0:42: +0:48
-          switchInt(move _8) -> [0: bb4, otherwise: bb5]; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
-      }
-  
-      bb1: {
-          _0 = const true;                 // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
-          goto -> bb3;                     // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
-      }
-  
-      bb2: {
-          StorageLive(_14);                // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
-          StorageLive(_15);                // scope 1 at $DIR/slice_filter.rs:+0:62: +0:68
--         StorageLive(_16);                // scope 1 at $DIR/slice_filter.rs:+0:62: +0:63
--         _16 = _5;                        // scope 1 at $DIR/slice_filter.rs:+0:62: +0:63
--         StorageLive(_17);                // scope 1 at $DIR/slice_filter.rs:+0:67: +0:68
--         _17 = _3;                        // scope 1 at $DIR/slice_filter.rs:+0:67: +0:68
--         _15 = Le(move _16, move _17);    // scope 1 at $DIR/slice_filter.rs:+0:62: +0:68
--         StorageDead(_17);                // scope 1 at $DIR/slice_filter.rs:+0:67: +0:68
--         StorageDead(_16);                // scope 1 at $DIR/slice_filter.rs:+0:67: +0:68
-+         _15 = Le(_5, _3);                // scope 1 at $DIR/slice_filter.rs:+0:62: +0:68
-          switchInt(move _15) -> [0: bb6, otherwise: bb7]; // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
-      }
-  
-      bb3: {
-          StorageDead(_14);                // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
-          StorageDead(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
--         StorageDead(_6);                 // scope 0 at $DIR/slice_filter.rs:+0:77: +0:78
--         StorageDead(_5);                 // scope 0 at $DIR/slice_filter.rs:+0:77: +0:78
--         StorageDead(_4);                 // scope 0 at $DIR/slice_filter.rs:+0:77: +0:78
--         StorageDead(_3);                 // scope 0 at $DIR/slice_filter.rs:+0:77: +0:78
-          return;                          // scope 0 at $DIR/slice_filter.rs:+0:78: +0:78
-      }
-  
-      bb4: {
-          _7 = const false;                // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
-          StorageDead(_11);                // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
-          StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
-          goto -> bb2;                     // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
-      }
-  
-      bb5: {
-          StorageLive(_11);                // scope 1 at $DIR/slice_filter.rs:+0:52: +0:58
--         StorageLive(_12);                // scope 1 at $DIR/slice_filter.rs:+0:52: +0:53
--         _12 = _6;                        // scope 1 at $DIR/slice_filter.rs:+0:52: +0:53
--         StorageLive(_13);                // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
--         _13 = _4;                        // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
--         _11 = Le(move _12, move _13);    // scope 1 at $DIR/slice_filter.rs:+0:52: +0:58
--         StorageDead(_13);                // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
--         StorageDead(_12);                // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
-+         _11 = Le(_6, _4);                // scope 1 at $DIR/slice_filter.rs:+0:52: +0:58
-          _7 = move _11;                   // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
-          StorageDead(_11);                // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
-          StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
-          switchInt(move _7) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
-      }
-  
-      bb6: {
-          _14 = const false;               // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
-          goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
-      }
-  
-      bb7: {
-          StorageLive(_18);                // scope 1 at $DIR/slice_filter.rs:+0:72: +0:78
--         StorageLive(_19);                // scope 1 at $DIR/slice_filter.rs:+0:72: +0:73
--         _19 = _4;                        // scope 1 at $DIR/slice_filter.rs:+0:72: +0:73
--         StorageLive(_20);                // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
--         _20 = _6;                        // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
--         _18 = Le(move _19, move _20);    // scope 1 at $DIR/slice_filter.rs:+0:72: +0:78
--         StorageDead(_20);                // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
--         StorageDead(_19);                // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
-+         _18 = Le(_4, _6);                // scope 1 at $DIR/slice_filter.rs:+0:72: +0:78
-          _14 = move _18;                  // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
-          goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
-      }
-  
-      bb8: {
-          StorageDead(_18);                // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
-          StorageDead(_15);                // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
-          _0 = move _14;                   // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
-          goto -> bb3;                     // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
-      }
-  }
-  
diff --git a/tests/mir-opt/slice_filter.variant_b-{closure#0}.DestinationPropagation.diff b/tests/mir-opt/slice_filter.variant_b-{closure#0}.DestinationPropagation.diff
deleted file mode 100644
index 45af6600cd4..00000000000
--- a/tests/mir-opt/slice_filter.variant_b-{closure#0}.DestinationPropagation.diff
+++ /dev/null
@@ -1,109 +0,0 @@
-- // MIR for `variant_b::{closure#0}` before DestinationPropagation
-+ // MIR for `variant_b::{closure#0}` after DestinationPropagation
-  
-  fn variant_b::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:12:25: 12:41], _2: &&(usize, usize, usize, usize)) -> bool {
-      let mut _0: bool;                    // return place in scope 0 at $DIR/slice_filter.rs:+0:42: +0:42
-      let _3: usize;                       // in scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
-      let _4: usize;                       // in scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
-      let _5: usize;                       // in scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
-      let _6: usize;                       // in scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
-      let mut _7: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:42: +0:58
-      let mut _8: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:42: +0:48
-      let mut _9: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:52: +0:58
-      let mut _10: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:62: +0:78
-      let mut _11: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:62: +0:68
-      let mut _12: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:72: +0:78
-      let mut _13: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
-      let mut _14: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
-      let mut _15: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
-      let mut _16: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
-      scope 1 {
-          debug a => _3;                   // in scope 1 at $DIR/slice_filter.rs:+0:29: +0:30
-          debug b => _4;                   // in scope 1 at $DIR/slice_filter.rs:+0:32: +0:33
-          debug c => _5;                   // in scope 1 at $DIR/slice_filter.rs:+0:35: +0:36
-          debug d => _6;                   // in scope 1 at $DIR/slice_filter.rs:+0:38: +0:39
-      }
-  
-      bb0: {
-          _13 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
-          _3 = ((*_13).0: usize);          // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
-          _14 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
-          _4 = ((*_14).1: usize);          // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
-          _15 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
-          _5 = ((*_15).2: usize);          // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
-          _16 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
-          _6 = ((*_16).3: usize);          // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
--         StorageLive(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
-          StorageLive(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:42: +0:48
-          _8 = Le(_3, _5);                 // scope 1 at $DIR/slice_filter.rs:+0:42: +0:48
-          switchInt(move _8) -> [0: bb4, otherwise: bb5]; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
-      }
-  
-      bb1: {
-          _0 = const true;                 // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
-          goto -> bb3;                     // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
-      }
-  
-      bb2: {
--         StorageLive(_10);                // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
-          StorageLive(_11);                // scope 1 at $DIR/slice_filter.rs:+0:62: +0:68
-          _11 = Le(_5, _3);                // scope 1 at $DIR/slice_filter.rs:+0:62: +0:68
-          switchInt(move _11) -> [0: bb6, otherwise: bb7]; // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
-      }
-  
-      bb3: {
--         StorageDead(_10);                // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
--         StorageDead(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
-          return;                          // scope 0 at $DIR/slice_filter.rs:+0:78: +0:78
-      }
-  
-      bb4: {
--         StorageDead(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
-          StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
-          goto -> bb2;                     // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
-      }
-  
-      bb5: {
--         StorageLive(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:52: +0:58
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:52: +0:58
-          _9 = Le(_6, _4);                 // scope 1 at $DIR/slice_filter.rs:+0:52: +0:58
--         _7 = move _9;                    // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
--         StorageDead(_9);                 // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
-          StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
--         switchInt(move _7) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
-+         switchInt(move _9) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
-      }
-  
-      bb6: {
--         _10 = const false;               // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
-+         _0 = const false;                // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
-          goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
-      }
-  
-      bb7: {
--         StorageLive(_12);                // scope 1 at $DIR/slice_filter.rs:+0:72: +0:78
--         _12 = Le(_4, _6);                // scope 1 at $DIR/slice_filter.rs:+0:72: +0:78
--         _10 = move _12;                  // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:72: +0:78
-+         _0 = Le(_4, _6);                 // scope 1 at $DIR/slice_filter.rs:+0:72: +0:78
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
-          goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
-      }
-  
-      bb8: {
--         StorageDead(_12);                // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
-          StorageDead(_11);                // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
--         _0 = move _10;                   // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
-+         nop;                             // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
-          goto -> bb3;                     // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
-      }
-  }
-  
diff --git a/tests/mir-opt/slice_filter.variant_b-{closure#0}.ReferencePropagation.diff b/tests/mir-opt/slice_filter.variant_b-{closure#0}.ReferencePropagation.diff
deleted file mode 100644
index d1241c6b024..00000000000
--- a/tests/mir-opt/slice_filter.variant_b-{closure#0}.ReferencePropagation.diff
+++ /dev/null
@@ -1,103 +0,0 @@
-- // MIR for `variant_b::{closure#0}` before ReferencePropagation
-+ // MIR for `variant_b::{closure#0}` after ReferencePropagation
-  
-  fn variant_b::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:12:25: 12:41], _2: &&(usize, usize, usize, usize)) -> bool {
-      let mut _0: bool;                    // return place in scope 0 at $DIR/slice_filter.rs:+0:42: +0:42
-      let _3: usize;                       // in scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
-      let _4: usize;                       // in scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
-      let _5: usize;                       // in scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
-      let _6: usize;                       // in scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
-      let mut _7: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:42: +0:58
-      let mut _8: bool;                    // in scope 0 at $DIR/slice_filter.rs:+0:42: +0:48
-      let mut _9: usize;                   // in scope 0 at $DIR/slice_filter.rs:+0:42: +0:43
-      let mut _10: usize;                  // in scope 0 at $DIR/slice_filter.rs:+0:47: +0:48
-      let mut _11: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:52: +0:58
-      let mut _12: usize;                  // in scope 0 at $DIR/slice_filter.rs:+0:52: +0:53
-      let mut _13: usize;                  // in scope 0 at $DIR/slice_filter.rs:+0:57: +0:58
-      let mut _14: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:62: +0:78
-      let mut _15: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:62: +0:68
-      let mut _16: usize;                  // in scope 0 at $DIR/slice_filter.rs:+0:62: +0:63
-      let mut _17: usize;                  // in scope 0 at $DIR/slice_filter.rs:+0:67: +0:68
-      let mut _18: bool;                   // in scope 0 at $DIR/slice_filter.rs:+0:72: +0:78
-      let mut _19: usize;                  // in scope 0 at $DIR/slice_filter.rs:+0:72: +0:73
-      let mut _20: usize;                  // in scope 0 at $DIR/slice_filter.rs:+0:77: +0:78
-      let mut _21: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
-      let mut _22: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
-      let mut _23: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
-      let mut _24: &(usize, usize, usize, usize); // in scope 0 at $DIR/slice_filter.rs:+0:26: +0:40
-      scope 1 {
-          debug a => _3;                   // in scope 1 at $DIR/slice_filter.rs:+0:29: +0:30
-          debug b => _4;                   // in scope 1 at $DIR/slice_filter.rs:+0:32: +0:33
-          debug c => _5;                   // in scope 1 at $DIR/slice_filter.rs:+0:35: +0:36
-          debug d => _6;                   // in scope 1 at $DIR/slice_filter.rs:+0:38: +0:39
-      }
-  
-      bb0: {
-          _21 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
-          _3 = ((*_21).0: usize);          // scope 0 at $DIR/slice_filter.rs:+0:29: +0:30
-          _22 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
-          _4 = ((*_22).1: usize);          // scope 0 at $DIR/slice_filter.rs:+0:32: +0:33
-          _23 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
-          _5 = ((*_23).2: usize);          // scope 0 at $DIR/slice_filter.rs:+0:35: +0:36
-          _24 = deref_copy (*_2);          // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
-          _6 = ((*_24).3: usize);          // scope 0 at $DIR/slice_filter.rs:+0:38: +0:39
-          StorageLive(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
-          StorageLive(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:42: +0:48
-          _8 = Le(_3, _5);                 // scope 1 at $DIR/slice_filter.rs:+0:42: +0:48
-          switchInt(move _8) -> [0: bb4, otherwise: bb5]; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
-      }
-  
-      bb1: {
-          _0 = const true;                 // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
-          goto -> bb3;                     // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
-      }
-  
-      bb2: {
-          StorageLive(_14);                // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
-          StorageLive(_15);                // scope 1 at $DIR/slice_filter.rs:+0:62: +0:68
-          _15 = Le(_5, _3);                // scope 1 at $DIR/slice_filter.rs:+0:62: +0:68
-          switchInt(move _15) -> [0: bb6, otherwise: bb7]; // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
-      }
-  
-      bb3: {
-          StorageDead(_14);                // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
-          StorageDead(_7);                 // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
-          return;                          // scope 0 at $DIR/slice_filter.rs:+0:78: +0:78
-      }
-  
-      bb4: {
-          _7 = const false;                // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
-          StorageDead(_11);                // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
-          StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
-          goto -> bb2;                     // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
-      }
-  
-      bb5: {
-          StorageLive(_11);                // scope 1 at $DIR/slice_filter.rs:+0:52: +0:58
-          _11 = Le(_6, _4);                // scope 1 at $DIR/slice_filter.rs:+0:52: +0:58
-          _7 = move _11;                   // scope 1 at $DIR/slice_filter.rs:+0:42: +0:58
-          StorageDead(_11);                // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
-          StorageDead(_8);                 // scope 1 at $DIR/slice_filter.rs:+0:57: +0:58
-          switchInt(move _7) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
-      }
-  
-      bb6: {
-          _14 = const false;               // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
-          goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
-      }
-  
-      bb7: {
-          StorageLive(_18);                // scope 1 at $DIR/slice_filter.rs:+0:72: +0:78
-          _18 = Le(_4, _6);                // scope 1 at $DIR/slice_filter.rs:+0:72: +0:78
-          _14 = move _18;                  // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
-          goto -> bb8;                     // scope 1 at $DIR/slice_filter.rs:+0:62: +0:78
-      }
-  
-      bb8: {
-          StorageDead(_18);                // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
-          StorageDead(_15);                // scope 1 at $DIR/slice_filter.rs:+0:77: +0:78
-          _0 = move _14;                   // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
-          goto -> bb3;                     // scope 1 at $DIR/slice_filter.rs:+0:42: +0:78
-      }
-  }
-  
diff --git a/tests/rustdoc-gui/codeblock-tooltip.goml b/tests/rustdoc-gui/codeblock-tooltip.goml
index e1c81ed79e4..7be5e39ba47 100644
--- a/tests/rustdoc-gui/codeblock-tooltip.goml
+++ b/tests/rustdoc-gui/codeblock-tooltip.goml
@@ -40,6 +40,7 @@ define-function: (
             "background-color": |background|,
             "border-color": |border|,
         })
+        click: ".docblock .example-wrap.compile_fail .tooltip"
 
         // should_panic block
         assert-css: (
@@ -71,6 +72,7 @@ define-function: (
             "background-color": |background|,
             "border-color": |border|,
         })
+        click: ".docblock .example-wrap.should_panic .tooltip"
 
         // ignore block
         assert-css: (
diff --git a/tests/rustdoc-gui/notable-trait.goml b/tests/rustdoc-gui/notable-trait.goml
index ecb57c274a5..371931d51fc 100644
--- a/tests/rustdoc-gui/notable-trait.goml
+++ b/tests/rustdoc-gui/notable-trait.goml
@@ -122,7 +122,7 @@ assert-count: ("//*[@class='tooltip popover']", 0)
 // Now check the colors.
 define-function: (
     "check-colors",
-    (theme, header_color, content_color, type_color, trait_color),
+    (theme, header_color, content_color, type_color, trait_color, link_color),
     block {
         go-to: "file://" + |DOC_PATH| + "/test_docs/struct.NotableStructWithLongName.html"
         // This is needed to ensure that the text color is computed.
@@ -133,8 +133,20 @@ define-function: (
         // We reload the page so the local storage settings are being used.
         reload:
 
+        assert-css: (
+             "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
+             {"color": |content_color|},
+             ALL,
+        )
+
         move-cursor-to: "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']"
-        assert-count: (".tooltip.popover", 1)
+        wait-for-count: (".tooltip.popover", 1)
+
+        assert-css: (
+             "//*[@id='method.create_an_iterator_from_read']//*[@class='tooltip']",
+             {"color": |link_color|},
+             ALL,
+        )
 
         assert-css: (
              ".tooltip.popover h3",
@@ -163,6 +175,7 @@ call-function: (
     "check-colors",
     {
         "theme": "ayu",
+        "link_color": "rgb(57, 175, 215)",
         "content_color": "rgb(230, 225, 207)",
         "header_color": "rgb(255, 255, 255)",
         "type_color": "rgb(255, 160, 165)",
@@ -174,6 +187,7 @@ call-function: (
     "check-colors",
     {
         "theme": "dark",
+        "link_color": "rgb(210, 153, 29)",
         "content_color": "rgb(221, 221, 221)",
         "header_color": "rgb(221, 221, 221)",
         "type_color": "rgb(45, 191, 184)",
@@ -185,6 +199,7 @@ call-function: (
     "check-colors",
     {
         "theme": "light",
+        "link_color": "rgb(56, 115, 173)",
         "content_color": "rgb(0, 0, 0)",
         "header_color": "rgb(0, 0, 0)",
         "type_color": "rgb(173, 55, 138)",
diff --git a/tests/rustdoc-gui/theme-in-history.goml b/tests/rustdoc-gui/theme-in-history.goml
index 8fcd0ecd309..42c5b5e6e69 100644
--- a/tests/rustdoc-gui/theme-in-history.goml
+++ b/tests/rustdoc-gui/theme-in-history.goml
@@ -7,7 +7,7 @@ set-local-storage: {
 }
 // We reload the page so the local storage settings are being used.
 reload:
-assert-css: ("body", { "background-color": "rgb(53, 53, 53)" })
+assert-css: ("body", { "background-color": "#353535" })
 assert-local-storage: { "rustdoc-theme": "dark" }
 
 // Now we go to the settings page.
@@ -15,7 +15,7 @@ go-to: "file://" + |DOC_PATH| + "/settings.html"
 wait-for: "#settings"
 // We change the theme to "light".
 click: "#theme-light"
-wait-for-css: ("body", { "background-color": "rgb(255, 255, 255)" })
+wait-for-css: ("body", { "background-color": "white" })
 assert-local-storage: { "rustdoc-theme": "light" }
 
 // We go back in history.
@@ -23,5 +23,5 @@ history-go-back:
 // Confirm that we're not on the settings page.
 assert-false: "#settings"
 // Check that the current theme is still "light".
-assert-css: ("body", { "background-color": "rgb(255, 255, 255)" })
+assert-css: ("body", { "background-color": "white" })
 assert-local-storage: { "rustdoc-theme": "light" }
diff --git a/tests/rustdoc/intra-doc/issue-108459.rs b/tests/rustdoc/intra-doc/issue-108459.rs
new file mode 100644
index 00000000000..eb1c7a05e54
--- /dev/null
+++ b/tests/rustdoc/intra-doc/issue-108459.rs
@@ -0,0 +1,37 @@
+#![deny(rustdoc::broken_intra_doc_links)]
+
+pub struct S;
+pub mod char {}
+
+// Ensure this doesn't ICE due to trying to slice off non-existent backticks from "S"
+
+/// See [S] and [`S`]
+pub struct MyStruct1;
+
+// Ensure that link texts are replaced correctly even if there are multiple links with
+// the same target but different text
+
+/// See also [crate::char] and [mod@char] and [prim@char]
+// @has issue_108459/struct.MyStruct2.html '//*[@href="char/index.html"]' 'crate::char'
+// @has - '//*[@href="char/index.html"]' 'char'
+// @has - '//*[@href="{{channel}}/std/primitive.char.html"]' 'char'
+pub struct MyStruct2;
+
+/// See also [mod@char] and [prim@char] and [crate::char]
+// @has issue_108459/struct.MyStruct3.html '//*[@href="char/index.html"]' 'crate::char'
+// @has - '//*[@href="char/index.html"]' 'char'
+// @has - '//*[@href="{{channel}}/std/primitive.char.html"]' 'char'
+pub struct MyStruct3;
+
+// Ensure that links are correct even if there are multiple links with the same text but
+// different targets
+
+/// See also [char][mod@char] and [char][prim@char]
+// @has issue_108459/struct.MyStruct4.html '//*[@href="char/index.html"]' 'char'
+// @has - '//*[@href="{{channel}}/std/primitive.char.html"]' 'char'
+pub struct MyStruct4;
+
+/// See also [char][prim@char] and [char][crate::char]
+// @has issue_108459/struct.MyStruct5.html '//*[@href="char/index.html"]' 'char'
+// @has - '//*[@href="{{channel}}/std/primitive.char.html"]' 'char'
+pub struct MyStruct5;
diff --git a/tests/rustdoc/intra-doc/prim-precedence.rs b/tests/rustdoc/intra-doc/prim-precedence.rs
index 25625b95277..c5a64e42a01 100644
--- a/tests/rustdoc/intra-doc/prim-precedence.rs
+++ b/tests/rustdoc/intra-doc/prim-precedence.rs
@@ -12,5 +12,5 @@ pub struct MyString;
 
 /// See also [crate::char] and [mod@char]
 // @has prim_precedence/struct.MyString2.html '//*[@href="char/index.html"]' 'crate::char'
-// @has - '//*[@href="char/index.html"]' 'mod@char'
+// @has - '//*[@href="char/index.html"]' 'char'
 pub struct MyString2;
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
index 39e34d73f9a..ffbefce48d3 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
@@ -538,7 +538,7 @@ struct LabelWithTrailingPath {
 #[diag(no_crate_example, code = "E0123")]
 struct LabelWithTrailingNameValue {
     #[label(no_crate_label, foo = "...")]
-    //~^ ERROR invalid nested attribute
+    //~^ ERROR only `no_span` is a valid nested attribute
     span: Span,
 }
 
@@ -546,7 +546,7 @@ struct LabelWithTrailingNameValue {
 #[diag(no_crate_example, code = "E0123")]
 struct LabelWithTrailingList {
     #[label(no_crate_label, foo("..."))]
-    //~^ ERROR invalid nested attribute
+    //~^ ERROR only `no_span` is a valid nested attribute
     span: Span,
 }
 
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index 801e4b5793c..1398f9c96bf 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -243,7 +243,7 @@ error: invalid nested attribute
 LL |     #[suggestion(nonsense = "bar")]
    |                  ^^^^^^^^
    |
-   = help: only `style`, `code` and `applicability` are valid nested attributes
+   = help: only `no_span`, `style`, `code` and `applicability` are valid nested attributes
 
 error: suggestion without `code = "..."`
   --> $DIR/diagnostic-derive.rs:234:5
@@ -257,7 +257,7 @@ error: invalid nested attribute
 LL |     #[suggestion(msg = "bar")]
    |                  ^^^
    |
-   = help: only `style`, `code` and `applicability` are valid nested attributes
+   = help: only `no_span`, `style`, `code` and `applicability` are valid nested attributes
 
 error: suggestion without `code = "..."`
   --> $DIR/diagnostic-derive.rs:243:5
@@ -335,13 +335,13 @@ error: a diagnostic slug must be the first argument to the attribute
 LL |     #[label(no_crate_label, foo)]
    |                                ^
 
-error: invalid nested attribute
+error: only `no_span` is a valid nested attribute
   --> $DIR/diagnostic-derive.rs:540:29
    |
 LL |     #[label(no_crate_label, foo = "...")]
    |                             ^^^
 
-error: invalid nested attribute
+error: only `no_span` is a valid nested attribute
   --> $DIR/diagnostic-derive.rs:548:29
    |
 LL |     #[label(no_crate_label, foo("..."))]
diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
index 1bfbb60015d..38af5b0f9fb 100644
--- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
+++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
@@ -85,7 +85,7 @@ struct F {
 
 #[derive(Subdiagnostic)]
 #[label(bug = "...")]
-//~^ ERROR invalid nested attribute
+//~^ ERROR only `no_span` is a valid nested attribute
 //~| ERROR diagnostic slug must be first argument
 struct G {
     #[primary_span]
@@ -104,7 +104,7 @@ struct H {
 
 #[derive(Subdiagnostic)]
 #[label(slug = 4)]
-//~^ ERROR invalid nested attribute
+//~^ ERROR only `no_span` is a valid nested attribute
 //~| ERROR diagnostic slug must be first argument
 struct J {
     #[primary_span]
@@ -114,7 +114,7 @@ struct J {
 
 #[derive(Subdiagnostic)]
 #[label(slug("..."))]
-//~^ ERROR invalid nested attribute
+//~^ ERROR only `no_span` is a valid nested attribute
 //~| ERROR diagnostic slug must be first argument
 struct K {
     #[primary_span]
@@ -143,7 +143,7 @@ struct M {
 
 #[derive(Subdiagnostic)]
 #[label(no_crate_example, code = "...")]
-//~^ ERROR invalid nested attribute
+//~^ ERROR only `no_span` is a valid nested attribute
 struct N {
     #[primary_span]
     span: Span,
@@ -152,7 +152,7 @@ struct N {
 
 #[derive(Subdiagnostic)]
 #[label(no_crate_example, applicability = "machine-applicable")]
-//~^ ERROR invalid nested attribute
+//~^ ERROR only `no_span` is a valid nested attribute
 struct O {
     #[primary_span]
     span: Span,
@@ -224,7 +224,7 @@ enum T {
 enum U {
     #[label(code = "...")]
     //~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute
-    //~| ERROR invalid nested attribute
+    //~| ERROR only `no_span` is a valid nested attribute
     A {
         #[primary_span]
         span: Span,
diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
index fca4f506890..5ddc8edd745 100644
--- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
@@ -26,7 +26,7 @@ error: `#[label = ...]` is not a valid attribute
 LL | #[label = "..."]
    | ^^^^^^^^^^^^^^^^
 
-error: invalid nested attribute
+error: only `no_span` is a valid nested attribute
   --> $DIR/subdiagnostic-derive.rs:87:9
    |
 LL | #[label(bug = "...")]
@@ -44,7 +44,7 @@ error: unexpected literal in nested attribute, expected ident
 LL | #[label("...")]
    |         ^^^^^
 
-error: invalid nested attribute
+error: only `no_span` is a valid nested attribute
   --> $DIR/subdiagnostic-derive.rs:106:9
    |
 LL | #[label(slug = 4)]
@@ -56,7 +56,7 @@ error: diagnostic slug must be first argument of a `#[label(...)]` attribute
 LL | #[label(slug = 4)]
    | ^^^^^^^^^^^^^^^^^^
 
-error: invalid nested attribute
+error: only `no_span` is a valid nested attribute
   --> $DIR/subdiagnostic-derive.rs:116:9
    |
 LL | #[label(slug("..."))]
@@ -74,13 +74,13 @@ error: unexpected end of input, unexpected token in nested attribute, expected i
 LL | #[label()]
    |         ^
 
-error: invalid nested attribute
+error: only `no_span` is a valid nested attribute
   --> $DIR/subdiagnostic-derive.rs:145:27
    |
 LL | #[label(no_crate_example, code = "...")]
    |                           ^^^^
 
-error: invalid nested attribute
+error: only `no_span` is a valid nested attribute
   --> $DIR/subdiagnostic-derive.rs:154:27
    |
 LL | #[label(no_crate_example, applicability = "machine-applicable")]
@@ -116,7 +116,7 @@ error: `#[bar(...)]` is not a valid attribute
 LL |     #[bar("...")]
    |     ^^^^^^^^^^^^^
 
-error: invalid nested attribute
+error: only `no_span` is a valid nested attribute
   --> $DIR/subdiagnostic-derive.rs:225:13
    |
 LL |     #[label(code = "...")]
@@ -312,7 +312,7 @@ error: invalid nested attribute
 LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")]
    |                                          ^^^^
    |
-   = help: only `style` and `applicability` are valid nested attributes
+   = help: only `no_span`, `style` and `applicability` are valid nested attributes
 
 error: multipart suggestion without any `#[suggestion_part(...)]` fields
   --> $DIR/subdiagnostic-derive.rs:540:1
diff --git a/tests/ui/chalkify/bugs/async.stderr b/tests/ui/chalkify/bugs/async.stderr
index 7e64e67f24c..e6d46b02706 100644
--- a/tests/ui/chalkify/bugs/async.stderr
+++ b/tests/ui/chalkify/bugs/async.stderr
@@ -13,16 +13,9 @@ error: internal compiler error: projection clauses should be implied from elsewh
 LL | async fn foo(x: u32) -> u32 {
    |                         ^^^query stack during panic:
 #0 [typeck] type-checking `foo`
-#1 [thir_body] building THIR for `foo`
-#2 [check_match] match-checking `foo`
-#3 [mir_built] building MIR for `foo`
-#4 [unsafety_check_result] unsafety-checking `foo`
-#5 [mir_const] preparing `foo` for borrow checking
-#6 [mir_promoted] promoting constants in MIR for `foo`
-#7 [mir_borrowck] borrow-checking `foo`
-#8 [type_of] computing type of `foo::{opaque#0}`
-#9 [check_mod_item_types] checking item types in top-level module
-#10 [analysis] running analysis passes on this crate
+#1 [type_of] computing type of `foo::{opaque#0}`
+#2 [check_mod_item_types] checking item types in top-level module
+#3 [analysis] running analysis passes on this crate
 end of query stack
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr
index 6aa8ee13b79..dc3a400cbaa 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/issue-80742.stderr
@@ -1,4 +1,4 @@
-error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed
+error[E0080]: evaluation of `Inline::<dyn Debug>::{constant#0}` failed
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
    |
    = note: size_of called on unsized type `dyn Debug`
@@ -35,7 +35,7 @@ help: consider relaxing the type parameter's implicit `Sized` bound
 LL | impl<T: ?Sized> Inline<T>
    |       ++++++++
 
-error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed
+error[E0080]: evaluation of `Inline::<dyn Debug>::{constant#0}` failed
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
    |
    = note: size_of called on unsized type `dyn Debug`
diff --git a/tests/ui/const-generics/issues/issue-100313.rs b/tests/ui/const-generics/issues/issue-100313.rs
index 4e9d3626aa8..9a9d4721c84 100644
--- a/tests/ui/const-generics/issues/issue-100313.rs
+++ b/tests/ui/const-generics/issues/issue-100313.rs
@@ -9,6 +9,7 @@ impl <const B: &'static bool> T<B> {
         unsafe {
             *(B as *const bool as *mut bool) = false;
             //~^ ERROR evaluation of constant value failed [E0080]
+            //~| ERROR casting `&T` to `&mut T` is undefined behavior
         }
     }
 }
diff --git a/tests/ui/const-generics/issues/issue-100313.stderr b/tests/ui/const-generics/issues/issue-100313.stderr
index d4b486376ca..ffc34a3a41e 100644
--- a/tests/ui/const-generics/issues/issue-100313.stderr
+++ b/tests/ui/const-generics/issues/issue-100313.stderr
@@ -1,3 +1,11 @@
+error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
+  --> $DIR/issue-100313.rs:10:13
+   |
+LL |             *(B as *const bool as *mut bool) = false;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[deny(cast_ref_to_mut)]` on by default
+
 error[E0080]: evaluation of constant value failed
   --> $DIR/issue-100313.rs:10:13
    |
@@ -10,11 +18,11 @@ note: inside `T::<&true>::set_false`
 LL |             *(B as *const bool as *mut bool) = false;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: inside `_`
-  --> $DIR/issue-100313.rs:18:5
+  --> $DIR/issue-100313.rs:19:5
    |
 LL |     x.set_false();
    |     ^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/const-ptr/forbidden_slices.stderr b/tests/ui/const-ptr/forbidden_slices.stderr
index 817cfb0acf9..22c3dfa64fe 100644
--- a/tests/ui/const-ptr/forbidden_slices.stderr
+++ b/tests/ui/const-ptr/forbidden_slices.stderr
@@ -54,11 +54,11 @@ error[E0080]: it is undefined behavior to use this value
 LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, size_of::<&u32>()) };
    | ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
    |
-   = help: this code performed an operation that depends on the underlying bytes representing a pointer
-   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
                HEX_DUMP
            }
+   = help: this code performed an operation that depends on the underlying bytes representing a pointer
+   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/forbidden_slices.rs:30:1
@@ -98,7 +98,7 @@ LL |     from_raw_parts(ptr, 1)
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-   = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
+   = note: out-of-bounds `offset_from`: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -156,11 +156,11 @@ error[E0080]: it is undefined behavior to use this value
 LL | pub static R5: &[u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
    |
-   = help: this code performed an operation that depends on the underlying bytes representing a pointer
-   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
                HEX_DUMP
            }
+   = help: this code performed an operation that depends on the underlying bytes representing a pointer
+   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/forbidden_slices.rs:63:1
diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr
index 8f3b3d5f700..23ba2c2f535 100644
--- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr
+++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr
@@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/alloc_intrinsic_errors.rs:9:17
    |
 LL |         let _ = intrinsics::const_allocate(4, 3) as *mut i32;
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ align has to be a power of 2, `3` is not a power of 2
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid align passed to `const_allocate`: 3 is not a power of 2
    |
 note: inside `foo`
   --> $DIR/alloc_intrinsic_errors.rs:9:17
diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.rs b/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.rs
index f746f27000f..9ae906bbb73 100644
--- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.rs
+++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.rs
@@ -4,11 +4,11 @@
 use std::intrinsics;
 
 const FOO: *const i32 = foo();
-//~^ ERROR untyped pointers are not allowed in constant
+//~^ ERROR unsupported untyped pointer in constant
 
 const fn foo() -> &'static i32 {
     let t = unsafe {
-        let i = intrinsics::const_allocate(4, 4) as * mut i32;
+        let i = intrinsics::const_allocate(4, 4) as *mut i32;
         *i = 20;
         i
     };
diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.stderr
index 00ab0dfc557..2103f842bd5 100644
--- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.stderr
+++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_nontransient_fail.stderr
@@ -1,8 +1,10 @@
-error: untyped pointers are not allowed in constant
+error: unsupported untyped pointer in constant
   --> $DIR/alloc_intrinsic_nontransient_fail.rs:6:1
    |
 LL | const FOO: *const i32 = foo();
    | ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: memory only reachable via raw pointers is not supported
 
 error: aborting due to previous error
 
diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs
index 77871c394b7..1354b3c33b3 100644
--- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs
+++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.rs
@@ -3,7 +3,7 @@
 #![feature(const_mut_refs)]
 use std::intrinsics;
 
-const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32};
-//~^ error: untyped pointers are not allowed in constant
+const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 };
+//~^ error: unsupported untyped pointer in constant
 
 fn main() {}
diff --git a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr
index 36002b850b7..b6276647350 100644
--- a/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr
+++ b/tests/ui/consts/const-eval/heap/alloc_intrinsic_untyped.stderr
@@ -1,8 +1,10 @@
-error: untyped pointers are not allowed in constant
+error: unsupported untyped pointer in constant
   --> $DIR/alloc_intrinsic_untyped.rs:6:1
    |
-LL | const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32};
+LL | const BAR: *mut i32 = unsafe { intrinsics::const_allocate(4, 4) as *mut i32 };
    | ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: memory only reachable via raw pointers is not supported
 
 error: aborting due to previous error
 
diff --git a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_incorrect_layout.stderr b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_incorrect_layout.stderr
index 650b409b190..4c23957a1f8 100644
--- a/tests/ui/consts/const-eval/heap/dealloc_intrinsic_incorrect_layout.stderr
+++ b/tests/ui/consts/const-eval/heap/dealloc_intrinsic_incorrect_layout.stderr
@@ -20,7 +20,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/dealloc_intrinsic_incorrect_layout.rs:25:5
    |
 LL |     intrinsics::const_deallocate(ptr, 4, 3);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ align has to be a power of 2, `3` is not a power of 2
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid align passed to `const_deallocate`: 3 is not a power of 2
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/consts/const-eval/infinite_loop.rs b/tests/ui/consts/const-eval/infinite_loop.rs
index 4babc9a2850..21781490637 100644
--- a/tests/ui/consts/const-eval/infinite_loop.rs
+++ b/tests/ui/consts/const-eval/infinite_loop.rs
@@ -4,8 +4,8 @@ fn main() {
     let _ = [(); {
         let mut n = 113383; // #20 in https://oeis.org/A006884
         while n != 0 {
-            //~^ ERROR evaluation of constant value failed
-            n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
+            //~^ ERROR is taking a long time
+            n = if n % 2 == 0 { n / 2 } else { 3 * n + 1 };
         }
         n
     }];
diff --git a/tests/ui/consts/const-eval/infinite_loop.stderr b/tests/ui/consts/const-eval/infinite_loop.stderr
index f30bfaf3f95..f0434a847ce 100644
--- a/tests/ui/consts/const-eval/infinite_loop.stderr
+++ b/tests/ui/consts/const-eval/infinite_loop.stderr
@@ -1,12 +1,27 @@
-error[E0080]: evaluation of constant value failed
+error: constant evaluation is taking a long time
   --> $DIR/infinite_loop.rs:6:9
    |
 LL | /         while n != 0 {
 LL | |
-LL | |             n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
+LL | |             n = if n % 2 == 0 { n / 2 } else { 3 * n + 1 };
 LL | |         }
-   | |_________^ exceeded interpreter step limit (see `#[const_eval_limit]`)
+   | |_________^
+   |
+   = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval.
+           If your compilation actually takes a long time, you can safely allow the lint.
+help: the constant being evaluated
+  --> $DIR/infinite_loop.rs:4:18
+   |
+LL |       let _ = [(); {
+   |  __________________^
+LL | |         let mut n = 113383; // #20 in https://oeis.org/A006884
+LL | |         while n != 0 {
+LL | |
+...  |
+LL | |         n
+LL | |     }];
+   | |_____^
+   = note: `#[deny(long_running_const_eval)]` on by default
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/issue-52475.rs b/tests/ui/consts/const-eval/issue-52475.rs
index 307c1a66834..ee26d280018 100644
--- a/tests/ui/consts/const-eval/issue-52475.rs
+++ b/tests/ui/consts/const-eval/issue-52475.rs
@@ -2,7 +2,8 @@ fn main() {
     let _ = [(); {
         let mut x = &0;
         let mut n = 0;
-        while n < 5 { //~ ERROR evaluation of constant value failed [E0080]
+        while n < 5 {
+            //~^ ERROR: constant evaluation is taking a long time
             n = (n + 1) % 5;
             x = &0; // Materialize a new AllocId
         }
diff --git a/tests/ui/consts/const-eval/issue-52475.stderr b/tests/ui/consts/const-eval/issue-52475.stderr
index 3aa6bd277dd..ebf9d12a66a 100644
--- a/tests/ui/consts/const-eval/issue-52475.stderr
+++ b/tests/ui/consts/const-eval/issue-52475.stderr
@@ -1,12 +1,28 @@
-error[E0080]: evaluation of constant value failed
+error: constant evaluation is taking a long time
   --> $DIR/issue-52475.rs:5:9
    |
 LL | /         while n < 5 {
+LL | |
 LL | |             n = (n + 1) % 5;
 LL | |             x = &0; // Materialize a new AllocId
 LL | |         }
-   | |_________^ exceeded interpreter step limit (see `#[const_eval_limit]`)
+   | |_________^
+   |
+   = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval.
+           If your compilation actually takes a long time, you can safely allow the lint.
+help: the constant being evaluated
+  --> $DIR/issue-52475.rs:2:18
+   |
+LL |       let _ = [(); {
+   |  __________________^
+LL | |         let mut x = &0;
+LL | |         let mut n = 0;
+LL | |         while n < 5 {
+...  |
+LL | |         0
+LL | |     }];
+   | |_____^
+   = note: `#[deny(long_running_const_eval)]` on by default
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/issue-70723.rs b/tests/ui/consts/const-eval/issue-70723.rs
index 3c81afa67a6..c8c809a25ed 100644
--- a/tests/ui/consts/const-eval/issue-70723.rs
+++ b/tests/ui/consts/const-eval/issue-70723.rs
@@ -1,3 +1,3 @@
-static _X: () = loop {}; //~ ERROR could not evaluate static initializer
+static _X: () = loop {}; //~ ERROR taking a long time
 
 fn main() {}
diff --git a/tests/ui/consts/const-eval/issue-70723.stderr b/tests/ui/consts/const-eval/issue-70723.stderr
index 09fb3e060dc..572a430726f 100644
--- a/tests/ui/consts/const-eval/issue-70723.stderr
+++ b/tests/ui/consts/const-eval/issue-70723.stderr
@@ -1,9 +1,17 @@
-error[E0080]: could not evaluate static initializer
+error: constant evaluation is taking a long time
   --> $DIR/issue-70723.rs:1:17
    |
 LL | static _X: () = loop {};
-   |                 ^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
+   |                 ^^^^^^^
+   |
+   = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval.
+           If your compilation actually takes a long time, you can safely allow the lint.
+help: the constant being evaluated
+  --> $DIR/issue-70723.rs:1:1
+   |
+LL | static _X: () = loop {};
+   | ^^^^^^^^^^^^^
+   = note: `#[deny(long_running_const_eval)]` on by default
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
index a93b561e5be..c0ddaceea4c 100644
--- a/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
+++ b/tests/ui/consts/const-eval/raw-bytes.32bit.stderr
@@ -35,7 +35,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/raw-bytes.rs:44:1
    |
 LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(D)>.0: encountered a value of uninhabited type Never
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(D)>.0: encountered a value of uninhabited type `Never`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 1, align: 1) {
@@ -290,11 +290,11 @@ error[E0080]: it is undefined behavior to use this value
 LL | const MYSTR_NO_INIT_ISSUE83182: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
    |
-   = help: this code performed an operation that depends on the underlying bytes representing a pointer
-   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: the raw bytes of the constant (size: 8, align: 4) {
                ╾ALLOC_ID╼ 01 00 00 00                         │ ╾──╼....
            }
+   = help: this code performed an operation that depends on the underlying bytes representing a pointer
+   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/raw-bytes.rs:152:1
@@ -529,11 +529,11 @@ error[E0080]: it is undefined behavior to use this value
 LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem::size_of::<&u32>()) };
    | ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
    |
-   = help: this code performed an operation that depends on the underlying bytes representing a pointer
-   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: the raw bytes of the constant (size: 8, align: 4) {
                ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
+   = help: this code performed an operation that depends on the underlying bytes representing a pointer
+   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/raw-bytes.rs:221:1
@@ -574,11 +574,11 @@ error[E0080]: it is undefined behavior to use this value
 LL | pub static R5: &[u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
    |
-   = help: this code performed an operation that depends on the underlying bytes representing a pointer
-   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: the raw bytes of the constant (size: 8, align: 4) {
                ╾ALLOC_ID╼ 04 00 00 00                         │ ╾──╼....
            }
+   = help: this code performed an operation that depends on the underlying bytes representing a pointer
+   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/raw-bytes.rs:242:1
diff --git a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
index a32d4863a38..20c905878e0 100644
--- a/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
+++ b/tests/ui/consts/const-eval/raw-bytes.64bit.stderr
@@ -35,7 +35,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/raw-bytes.rs:44:1
    |
 LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(D)>.0: encountered a value of uninhabited type Never
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(D)>.0: encountered a value of uninhabited type `Never`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: 1, align: 1) {
@@ -290,11 +290,11 @@ error[E0080]: it is undefined behavior to use this value
 LL | const MYSTR_NO_INIT_ISSUE83182: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
    |
-   = help: this code performed an operation that depends on the underlying bytes representing a pointer
-   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: the raw bytes of the constant (size: 16, align: 8) {
                ╾ALLOC_ID╼ 01 00 00 00 00 00 00 00 │ ╾──────╼........
            }
+   = help: this code performed an operation that depends on the underlying bytes representing a pointer
+   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/raw-bytes.rs:152:1
@@ -529,11 +529,11 @@ error[E0080]: it is undefined behavior to use this value
 LL | pub static S5: &[u8] = unsafe { from_raw_parts((&D3) as *const _ as _, mem::size_of::<&u32>()) };
    | ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
    |
-   = help: this code performed an operation that depends on the underlying bytes representing a pointer
-   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: the raw bytes of the constant (size: 16, align: 8) {
                ╾ALLOC_ID╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
            }
+   = help: this code performed an operation that depends on the underlying bytes representing a pointer
+   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/raw-bytes.rs:221:1
@@ -574,11 +574,11 @@ error[E0080]: it is undefined behavior to use this value
 LL | pub static R5: &[u8] = unsafe {
    | ^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
    |
-   = help: this code performed an operation that depends on the underlying bytes representing a pointer
-   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: the raw bytes of the constant (size: 16, align: 8) {
                ╾ALLOC_ID╼ 08 00 00 00 00 00 00 00 │ ╾──────╼........
            }
+   = help: this code performed an operation that depends on the underlying bytes representing a pointer
+   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/raw-bytes.rs:242:1
diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.rs b/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.rs
index c59596238e1..a30518170ad 100644
--- a/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.rs
+++ b/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.rs
@@ -25,7 +25,7 @@ const fn call_foo() -> u32 {
     foo();
     foo();
     foo();
-    foo(); //~ ERROR evaluation of constant value failed [E0080]
+    foo(); //~ ERROR is taking a long time
     0
 }
 
diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr
index ed70975af34..a3fd712ca46 100644
--- a/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr
+++ b/tests/ui/consts/const-eval/stable-metric/ctfe-fn-call.stderr
@@ -1,20 +1,17 @@
-error[E0080]: evaluation of constant value failed
-  --> $DIR/ctfe-fn-call.rs:28:5
-   |
-LL |     foo();
-   |     ^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
-   |
-note: inside `call_foo`
+error: constant evaluation is taking a long time
   --> $DIR/ctfe-fn-call.rs:28:5
    |
 LL |     foo();
    |     ^^^^^
-note: inside `X`
-  --> $DIR/ctfe-fn-call.rs:32:16
+   |
+   = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval.
+           If your compilation actually takes a long time, you can safely allow the lint.
+help: the constant being evaluated
+  --> $DIR/ctfe-fn-call.rs:32:1
    |
 LL | const X: u32 = call_foo();
-   |                ^^^^^^^^^^
+   | ^^^^^^^^^^^^
+   = note: `#[deny(long_running_const_eval)]` on by default
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.rs b/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.rs
index c10b8d83791..f7cd04568be 100644
--- a/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.rs
+++ b/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.rs
@@ -3,9 +3,10 @@
 
 const fn labelled_loop(n: u32) -> u32 {
     let mut i = 0;
-    'mylabel: loop { //~ ERROR evaluation of constant value failed [E0080]
+    'mylabel: loop {
+        //~^ ERROR is taking a long time
         if i > n {
-            break 'mylabel
+            break 'mylabel;
         }
         i += 1;
     }
diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.stderr
index d9404edd5b1..5808ee35a6b 100644
--- a/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.stderr
+++ b/tests/ui/consts/const-eval/stable-metric/ctfe-labelled-loop.stderr
@@ -1,30 +1,23 @@
-error[E0080]: evaluation of constant value failed
+error: constant evaluation is taking a long time
   --> $DIR/ctfe-labelled-loop.rs:6:5
    |
 LL | /     'mylabel: loop {
+LL | |
 LL | |         if i > n {
-LL | |             break 'mylabel
-LL | |         }
-LL | |         i += 1;
-LL | |     }
-   | |_____^ exceeded interpreter step limit (see `#[const_eval_limit]`)
-   |
-note: inside `labelled_loop`
-  --> $DIR/ctfe-labelled-loop.rs:6:5
-   |
-LL | /     'mylabel: loop {
-LL | |         if i > n {
-LL | |             break 'mylabel
+LL | |             break 'mylabel;
 LL | |         }
 LL | |         i += 1;
 LL | |     }
    | |_____^
-note: inside `X`
-  --> $DIR/ctfe-labelled-loop.rs:15:16
+   |
+   = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval.
+           If your compilation actually takes a long time, you can safely allow the lint.
+help: the constant being evaluated
+  --> $DIR/ctfe-labelled-loop.rs:16:1
    |
 LL | const X: u32 = labelled_loop(19);
-   |                ^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^
+   = note: `#[deny(long_running_const_eval)]` on by default
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.rs b/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.rs
index 80ff835f3e8..56a39fc45b0 100644
--- a/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.rs
+++ b/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.rs
@@ -1,11 +1,12 @@
 // check-fail
 // compile-flags: -Z tiny-const-eval-limit
 
+#[rustfmt::skip]
 const fn recurse(n: u32) -> u32 {
     if n == 0 {
         n
     } else {
-        recurse(n - 1) //~ ERROR evaluation of constant value failed [E0080]
+        recurse(n - 1) //~ ERROR is taking a long time
     }
 }
 
diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr
index ed9a3111942..524c8e55426 100644
--- a/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr
+++ b/tests/ui/consts/const-eval/stable-metric/ctfe-recursion.stderr
@@ -1,25 +1,17 @@
-error[E0080]: evaluation of constant value failed
-  --> $DIR/ctfe-recursion.rs:8:9
-   |
-LL |         recurse(n - 1)
-   |         ^^^^^^^^^^^^^^ exceeded interpreter step limit (see `#[const_eval_limit]`)
-   |
-note: inside `recurse`
-  --> $DIR/ctfe-recursion.rs:8:9
+error: constant evaluation is taking a long time
+  --> $DIR/ctfe-recursion.rs:9:9
    |
 LL |         recurse(n - 1)
    |         ^^^^^^^^^^^^^^
-note: [... 18 additional calls inside `recurse` ...]
-  --> $DIR/ctfe-recursion.rs:8:9
    |
-LL |         recurse(n - 1)
-   |         ^^^^^^^^^^^^^^
-note: inside `X`
-  --> $DIR/ctfe-recursion.rs:12:16
+   = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval.
+           If your compilation actually takes a long time, you can safely allow the lint.
+help: the constant being evaluated
+  --> $DIR/ctfe-recursion.rs:13:1
    |
 LL | const X: u32 = recurse(19);
-   |                ^^^^^^^^^^^
+   | ^^^^^^^^^^^^
+   = note: `#[deny(long_running_const_eval)]` on by default
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.allow.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.allow.stderr
new file mode 100644
index 00000000000..30550f93ac1
--- /dev/null
+++ b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.allow.stderr
@@ -0,0 +1,19 @@
+warning: constant evaluation is taking a long time
+  --> $DIR/ctfe-simple-loop.rs:9:5
+   |
+LL | /     while index < n {
+LL | |
+LL | |
+LL | |
+LL | |         index = index + 1;
+LL | |     }
+   | |_____^ the const evaluator is currently interpreting this expression
+   |
+help: the constant being evaluated
+  --> $DIR/ctfe-simple-loop.rs:19:1
+   |
+LL | const Y: u32 = simple_loop(35);
+   | ^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.rs b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.rs
index ca0eec93c5d..214f33dfb36 100644
--- a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.rs
+++ b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.rs
@@ -1,14 +1,22 @@
-// check-fail
+// check-pass
+// revisions: warn allow
+#![cfg_attr(warn, warn(long_running_const_eval))]
+#![cfg_attr(allow, allow(long_running_const_eval))]
+
 // compile-flags: -Z tiny-const-eval-limit
 const fn simple_loop(n: u32) -> u32 {
     let mut index = 0;
-    while index < n { //~ ERROR evaluation of constant value failed [E0080]
+    while index < n {
+        //~^ WARN is taking a long time
+        //[warn]~| WARN is taking a long time
+        //[warn]~| WARN is taking a long time
         index = index + 1;
     }
     0
 }
 
 const X: u32 = simple_loop(19);
+const Y: u32 = simple_loop(35);
 
 fn main() {
     println!("{X}");
diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.stderr
deleted file mode 100644
index 83ff275de70..00000000000
--- a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.stderr
+++ /dev/null
@@ -1,24 +0,0 @@
-error[E0080]: evaluation of constant value failed
-  --> $DIR/ctfe-simple-loop.rs:5:5
-   |
-LL | /     while index < n {
-LL | |         index = index + 1;
-LL | |     }
-   | |_____^ exceeded interpreter step limit (see `#[const_eval_limit]`)
-   |
-note: inside `simple_loop`
-  --> $DIR/ctfe-simple-loop.rs:5:5
-   |
-LL | /     while index < n {
-LL | |         index = index + 1;
-LL | |     }
-   | |_____^
-note: inside `X`
-  --> $DIR/ctfe-simple-loop.rs:11:16
-   |
-LL | const X: u32 = simple_loop(19);
-   |                ^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr
new file mode 100644
index 00000000000..40fc4a876e9
--- /dev/null
+++ b/tests/ui/consts/const-eval/stable-metric/ctfe-simple-loop.warn.stderr
@@ -0,0 +1,62 @@
+warning: constant evaluation is taking a long time
+  --> $DIR/ctfe-simple-loop.rs:9:5
+   |
+LL | /     while index < n {
+LL | |
+LL | |
+LL | |
+LL | |         index = index + 1;
+LL | |     }
+   | |_____^
+   |
+   = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval.
+           If your compilation actually takes a long time, you can safely allow the lint.
+help: the constant being evaluated
+  --> $DIR/ctfe-simple-loop.rs:18:1
+   |
+LL | const X: u32 = simple_loop(19);
+   | ^^^^^^^^^^^^
+note: the lint level is defined here
+  --> $DIR/ctfe-simple-loop.rs:3:24
+   |
+LL | #![cfg_attr(warn, warn(long_running_const_eval))]
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: constant evaluation is taking a long time
+  --> $DIR/ctfe-simple-loop.rs:9:5
+   |
+LL | /     while index < n {
+LL | |
+LL | |
+LL | |
+LL | |         index = index + 1;
+LL | |     }
+   | |_____^
+   |
+   = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval.
+           If your compilation actually takes a long time, you can safely allow the lint.
+help: the constant being evaluated
+  --> $DIR/ctfe-simple-loop.rs:19:1
+   |
+LL | const Y: u32 = simple_loop(35);
+   | ^^^^^^^^^^^^
+
+warning: constant evaluation is taking a long time
+  --> $DIR/ctfe-simple-loop.rs:9:5
+   |
+LL | /     while index < n {
+LL | |
+LL | |
+LL | |
+LL | |         index = index + 1;
+LL | |     }
+   | |_____^ the const evaluator is currently interpreting this expression
+   |
+help: the constant being evaluated
+  --> $DIR/ctfe-simple-loop.rs:19:1
+   |
+LL | const Y: u32 = simple_loop(35);
+   | ^^^^^^^^^^^^
+
+warning: 3 warnings emitted
+
diff --git a/tests/ui/consts/const-eval/ub-enum.32bit.stderr b/tests/ui/consts/const-eval/ub-enum.32bit.stderr
index 3ad1ac974c8..1810600b785 100644
--- a/tests/ui/consts/const-eval/ub-enum.32bit.stderr
+++ b/tests/ui/consts/const-eval/ub-enum.32bit.stderr
@@ -86,7 +86,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:83:1
    |
 LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(D)>.0: encountered a value of uninhabited type Never
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(D)>.0: encountered a value of uninhabited type `Never`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
@@ -108,7 +108,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/ub-enum.rs:96:77
    |
 LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
-   |                                                                             ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Ok)>.0.1: encountered a value of uninhabited type Never
+   |                                                                             ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Ok)>.0.1: encountered a value of uninhabited type `Never`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/ub-enum.rs:98:77
diff --git a/tests/ui/consts/const-eval/ub-enum.64bit.stderr b/tests/ui/consts/const-eval/ub-enum.64bit.stderr
index a66706d1af9..fb40babb0b9 100644
--- a/tests/ui/consts/const-eval/ub-enum.64bit.stderr
+++ b/tests/ui/consts/const-eval/ub-enum.64bit.stderr
@@ -86,7 +86,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:83:1
    |
 LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(D)>.0: encountered a value of uninhabited type Never
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(D)>.0: encountered a value of uninhabited type `Never`
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
    = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
@@ -108,7 +108,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/ub-enum.rs:96:77
    |
 LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(0u64) };
-   |                                                                             ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Ok)>.0.1: encountered a value of uninhabited type Never
+   |                                                                             ^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .<enum-variant(Ok)>.0.1: encountered a value of uninhabited type `Never`
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/ub-enum.rs:98:77
diff --git a/tests/ui/consts/const-eval/ub-uninhabit.stderr b/tests/ui/consts/const-eval/ub-uninhabit.stderr
index 733975fc0e9..f1ad0f04d3d 100644
--- a/tests/ui/consts/const-eval/ub-uninhabit.stderr
+++ b/tests/ui/consts/const-eval/ub-uninhabit.stderr
@@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/ub-uninhabit.rs:16:35
    |
 LL | const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init };
-   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a value of uninhabited type Bar
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a value of uninhabited type `Bar`
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-uninhabit.rs:19:1
@@ -19,7 +19,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/ub-uninhabit.rs:22:42
    |
 LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init };
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered a value of uninhabited type Bar
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered a value of uninhabited type `Bar`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr b/tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
index 74bc6317c80..b423edbdcec 100644
--- a/tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
+++ b/tests/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
@@ -28,7 +28,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/validate_uninhabited_zsts.rs:21:42
    |
 LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered a value of uninhabited type empty::Void
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered a value of uninhabited type `Void`
 
 warning: the type `empty::Empty` does not permit zero-initialization
   --> $DIR/validate_uninhabited_zsts.rs:21:42
diff --git a/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr b/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
index 74bc6317c80..b423edbdcec 100644
--- a/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
+++ b/tests/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
@@ -28,7 +28,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/validate_uninhabited_zsts.rs:21:42
    |
 LL | const BAR: [empty::Empty; 3] = [unsafe { std::mem::transmute(()) }; 3];
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered a value of uninhabited type empty::Void
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at .0: encountered a value of uninhabited type `Void`
 
 warning: the type `empty::Empty` does not permit zero-initialization
   --> $DIR/validate_uninhabited_zsts.rs:21:42
diff --git a/tests/ui/consts/const_limit/const_eval_limit_not_reached.rs b/tests/ui/consts/const_limit/const_eval_limit_not_reached.rs
deleted file mode 100644
index 629d1f02a30..00000000000
--- a/tests/ui/consts/const_limit/const_eval_limit_not_reached.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-// check-pass
-
-#![feature(const_eval_limit)]
-
-// This needs to be higher than the number of loop iterations since each pass through the loop may
-// hit more than one terminator.
-#![const_eval_limit="4000"]
-
-const X: usize = {
-    let mut x = 0;
-    while x != 1000 {
-        x += 1;
-    }
-
-    x
-};
-
-fn main() {
-    assert_eq!(X, 1000);
-}
diff --git a/tests/ui/consts/const_limit/const_eval_limit_overflow.rs b/tests/ui/consts/const_limit/const_eval_limit_overflow.rs
deleted file mode 100644
index 1c49593cd53..00000000000
--- a/tests/ui/consts/const_limit/const_eval_limit_overflow.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-#![feature(const_eval_limit)]
-#![const_eval_limit="18_446_744_073_709_551_615"]
-//~^ ERROR `limit` must be a non-negative integer
-
-const CONSTANT: usize = limit();
-
-fn main() {
-    assert_eq!(CONSTANT, 1764);
-}
-
-const fn limit() -> usize {
-    let x = 42;
-
-    x * 42
-}
diff --git a/tests/ui/consts/const_limit/const_eval_limit_overflow.stderr b/tests/ui/consts/const_limit/const_eval_limit_overflow.stderr
deleted file mode 100644
index 7f5d5e6cd4c..00000000000
--- a/tests/ui/consts/const_limit/const_eval_limit_overflow.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-error: `limit` must be a non-negative integer
-  --> $DIR/const_eval_limit_overflow.rs:2:1
-   |
-LL | #![const_eval_limit="18_446_744_073_709_551_615"]
-   | ^^^^^^^^^^^^^^^^^^^^----------------------------^
-   |                     |
-   |                     not a valid integer
-
-error: aborting due to previous error
-
diff --git a/tests/ui/consts/const_limit/const_eval_limit_reached.rs b/tests/ui/consts/const_limit/const_eval_limit_reached.rs
deleted file mode 100644
index 3ce038c1d3f..00000000000
--- a/tests/ui/consts/const_limit/const_eval_limit_reached.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-#![feature(const_eval_limit)]
-#![const_eval_limit = "500"]
-
-const X: usize = {
-    let mut x = 0;
-    while x != 1000 {
-        //~^ ERROR evaluation of constant value failed
-        x += 1;
-    }
-
-    x
-};
-
-fn main() {
-    assert_eq!(X, 1000);
-}
diff --git a/tests/ui/consts/const_limit/const_eval_limit_reached.stderr b/tests/ui/consts/const_limit/const_eval_limit_reached.stderr
deleted file mode 100644
index a8e8ae9bb08..00000000000
--- a/tests/ui/consts/const_limit/const_eval_limit_reached.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0080]: evaluation of constant value failed
-  --> $DIR/const_eval_limit_reached.rs:6:5
-   |
-LL | /     while x != 1000 {
-LL | |
-LL | |         x += 1;
-LL | |     }
-   | |_____^ exceeded interpreter step limit (see `#[const_eval_limit]`)
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const_limit/feature-gate-const_eval_limit.rs b/tests/ui/consts/const_limit/feature-gate-const_eval_limit.rs
deleted file mode 100644
index 61119d7511d..00000000000
--- a/tests/ui/consts/const_limit/feature-gate-const_eval_limit.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-#![const_eval_limit="42"]
-//~^ ERROR the `#[const_eval_limit]` attribute is an experimental feature [E0658]
-
-const CONSTANT: usize = limit();
-
-fn main() {
-    assert_eq!(CONSTANT, 1764);
-}
-
-const fn limit() -> usize {
-    let x = 42;
-
-    x * 42
-}
diff --git a/tests/ui/consts/const_limit/feature-gate-const_eval_limit.stderr b/tests/ui/consts/const_limit/feature-gate-const_eval_limit.stderr
deleted file mode 100644
index 5bd29c7dfd2..00000000000
--- a/tests/ui/consts/const_limit/feature-gate-const_eval_limit.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0658]: the `#[const_eval_limit]` attribute is an experimental feature
-  --> $DIR/feature-gate-const_eval_limit.rs:1:1
-   |
-LL | #![const_eval_limit="42"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #67217 <https://github.com/rust-lang/rust/issues/67217> for more information
-   = help: add `#![feature(const_eval_limit)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/consts/issue-64506.stderr b/tests/ui/consts/issue-64506.stderr
index 31a5b1df837..2fe84245b3e 100644
--- a/tests/ui/consts/issue-64506.stderr
+++ b/tests/ui/consts/issue-64506.stderr
@@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/issue-64506.rs:16:22
    |
 LL |     let x = unsafe { Foo { b: () }.a };
-   |                      ^^^^^^^^^^^^^^^ constructing invalid value at .inner: encountered a value of uninhabited type AnonPipe
+   |                      ^^^^^^^^^^^^^^^ constructing invalid value at .inner: encountered a value of uninhabited type `AnonPipe`
 
 error: aborting due to previous error
 
diff --git a/tests/ui/consts/issue-83182.stderr b/tests/ui/consts/issue-83182.stderr
index 1d578f910c0..ca4e0f7aa02 100644
--- a/tests/ui/consts/issue-83182.stderr
+++ b/tests/ui/consts/issue-83182.stderr
@@ -4,11 +4,11 @@ error[E0080]: it is undefined behavior to use this value
 LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[&()]) };
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
    |
-   = help: this code performed an operation that depends on the underlying bytes representing a pointer
-   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
    = note: the raw bytes of the constant (size: $SIZE, align: $ALIGN) {
                HEX_DUMP
            }
+   = help: this code performed an operation that depends on the underlying bytes representing a pointer
+   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error: aborting due to previous error
 
diff --git a/tests/ui/consts/issue-miri-1910.stderr b/tests/ui/consts/issue-miri-1910.stderr
index fb758d406b5..67797e6fb5a 100644
--- a/tests/ui/consts/issue-miri-1910.stderr
+++ b/tests/ui/consts/issue-miri-1910.stderr
@@ -3,8 +3,6 @@ error[E0080]: evaluation of constant value failed
    |
    = note: unable to turn pointer into raw bytes
    |
-   = help: this code performed an operation that depends on the underlying bytes representing a pointer
-   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 note: inside `std::ptr::read::<u8>`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
 note: inside `ptr::const_ptr::<impl *const u8>::read`
@@ -14,6 +12,8 @@ note: inside `C`
    |
 LL |     (&foo as *const _ as *const u8).add(one_and_a_half_pointers).read();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: this code performed an operation that depends on the underlying bytes representing a pointer
+   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error: aborting due to previous error
 
diff --git a/tests/ui/consts/miri_unleashed/assoc_const.stderr b/tests/ui/consts/miri_unleashed/assoc_const.stderr
index 8e22cb74bf5..d97097d352a 100644
--- a/tests/ui/consts/miri_unleashed/assoc_const.stderr
+++ b/tests/ui/consts/miri_unleashed/assoc_const.stderr
@@ -1,4 +1,4 @@
-error[E0080]: evaluation of `<std::string::String as Bar<std::vec::Vec<u32>, std::string::String>>::F` failed
+error[E0080]: evaluation of `<String as Bar<Vec<u32>, String>>::F` failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
    = note: calling non-const function `<Vec<u32> as Drop>::drop`
diff --git a/tests/ui/consts/miri_unleashed/raw_mutable_const.rs b/tests/ui/consts/miri_unleashed/raw_mutable_const.rs
index 5f8ec4e6e29..adb1f8bf3ec 100644
--- a/tests/ui/consts/miri_unleashed/raw_mutable_const.rs
+++ b/tests/ui/consts/miri_unleashed/raw_mutable_const.rs
@@ -3,6 +3,6 @@
 use std::cell::UnsafeCell;
 
 const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
-//~^ ERROR: untyped pointers are not allowed in constant
+//~^ ERROR: unsupported untyped pointer in constant
 
 fn main() {}
diff --git a/tests/ui/consts/miri_unleashed/raw_mutable_const.stderr b/tests/ui/consts/miri_unleashed/raw_mutable_const.stderr
index f8dc11d695f..5acdcdd95e8 100644
--- a/tests/ui/consts/miri_unleashed/raw_mutable_const.stderr
+++ b/tests/ui/consts/miri_unleashed/raw_mutable_const.stderr
@@ -1,8 +1,10 @@
-error: untyped pointers are not allowed in constant
+error: unsupported untyped pointer in constant
   --> $DIR/raw_mutable_const.rs:5:1
    |
 LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: memory only reachable via raw pointers is not supported
 
 warning: skipping const checks
    |
diff --git a/tests/ui/consts/missing_span_in_backtrace.stderr b/tests/ui/consts/missing_span_in_backtrace.stderr
index e6d3d51990d..fcfb9fbb3f8 100644
--- a/tests/ui/consts/missing_span_in_backtrace.stderr
+++ b/tests/ui/consts/missing_span_in_backtrace.stderr
@@ -3,8 +3,6 @@ error[E0080]: evaluation of constant value failed
    |
    = note: unable to copy parts of a pointer from memory at ALLOC_ID
    |
-   = help: this code performed an operation that depends on the underlying bytes representing a pointer
-   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 note: inside `std::ptr::read::<MaybeUninit<MaybeUninit<u8>>>`
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
 note: inside `mem::swap_simple::<MaybeUninit<MaybeUninit<u8>>>`
@@ -22,6 +20,8 @@ note: inside `X`
 20 | |             mem::size_of::<&i32>(),
 21 | |         );
    | |_________^
+   = help: this code performed an operation that depends on the underlying bytes representing a pointer
+   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
 
 error: aborting due to previous error
 
diff --git a/tests/ui/consts/offset_from_ub.stderr b/tests/ui/consts/offset_from_ub.stderr
index 6530084a585..97ff6efdd79 100644
--- a/tests/ui/consts/offset_from_ub.stderr
+++ b/tests/ui/consts/offset_from_ub.stderr
@@ -27,31 +27,31 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/offset_from_ub.rs:37:14
    |
 LL |     unsafe { ptr_offset_from(ptr, ptr) }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: null pointer is a dangling pointer (it has no provenance)
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_from_ub.rs:44:14
    |
 LL |     unsafe { ptr_offset_from(ptr2, ptr1) }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: 0x8[noalloc] is a dangling pointer (it has no provenance)
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: 0x8[noalloc] is a dangling pointer (it has no provenance)
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_from_ub.rs:53:14
    |
 LL |     unsafe { ptr_offset_from(end_ptr, start_ptr) }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc17 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: alloc17 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_from_ub.rs:62:14
    |
 LL |     unsafe { ptr_offset_from(start_ptr, end_ptr) }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc20 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: alloc20 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_from_ub.rs:70:14
    |
 LL |     unsafe { ptr_offset_from(end_ptr, end_ptr) }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc23 has size 4, so pointer at offset 10 is out-of-bounds
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds `offset_from`: alloc23 has size 4, so pointer at offset 10 is out-of-bounds
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_from_ub.rs:79:14
@@ -86,7 +86,7 @@ LL |     unsafe { ptr_offset_from_unsigned(ptr2, ptr1) }
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-   = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
+   = note: out-of-bounds `offset_from`: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset_from`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
@@ -99,7 +99,7 @@ LL |     unsafe { ptr2.offset_from(ptr1) }
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-   = note: out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
+   = note: out-of-bounds `offset_from`: null pointer is a dangling pointer (it has no provenance)
    |
 note: inside `ptr::const_ptr::<impl *const u8>::offset_from`
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
diff --git a/tests/ui/consts/raw-ptr-const.rs b/tests/ui/consts/raw-ptr-const.rs
index b9c542d03d5..fc774be54df 100644
--- a/tests/ui/consts/raw-ptr-const.rs
+++ b/tests/ui/consts/raw-ptr-const.rs
@@ -3,6 +3,6 @@
 // could also be allowed.
 
 const CONST_RAW: *const Vec<i32> = &Vec::new() as *const _;
-//~^ ERROR untyped pointers are not allowed in constant
+//~^ ERROR unsupported untyped pointer in constant
 
 fn main() {}
diff --git a/tests/ui/consts/raw-ptr-const.stderr b/tests/ui/consts/raw-ptr-const.stderr
index f7b53433b69..82f782fab7f 100644
--- a/tests/ui/consts/raw-ptr-const.stderr
+++ b/tests/ui/consts/raw-ptr-const.stderr
@@ -1,8 +1,10 @@
-error: untyped pointers are not allowed in constant
+error: unsupported untyped pointer in constant
   --> $DIR/raw-ptr-const.rs:5:1
    |
 LL | const CONST_RAW: *const Vec<i32> = &Vec::new() as *const _;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: memory only reachable via raw pointers is not supported
 
 error: aborting due to previous error
 
diff --git a/tests/ui/dyn-star/param-env-infer.next.stderr b/tests/ui/dyn-star/param-env-infer.next.stderr
index 64d76bb04b1..408abecc30d 100644
--- a/tests/ui/dyn-star/param-env-infer.next.stderr
+++ b/tests/ui/dyn-star/param-env-infer.next.stderr
@@ -13,41 +13,6 @@ error[E0391]: cycle detected when computing type of `make_dyn_star::{opaque#0}`
 LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
    |                                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: ...which requires borrow-checking `make_dyn_star`...
-  --> $DIR/param-env-infer.rs:11:1
-   |
-LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires promoting constants in MIR for `make_dyn_star`...
-  --> $DIR/param-env-infer.rs:11:1
-   |
-LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires preparing `make_dyn_star` for borrow checking...
-  --> $DIR/param-env-infer.rs:11:1
-   |
-LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires unsafety-checking `make_dyn_star`...
-  --> $DIR/param-env-infer.rs:11:1
-   |
-LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires building MIR for `make_dyn_star`...
-  --> $DIR/param-env-infer.rs:11:1
-   |
-LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires match-checking `make_dyn_star`...
-  --> $DIR/param-env-infer.rs:11:1
-   |
-LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires building THIR for `make_dyn_star`...
-  --> $DIR/param-env-infer.rs:11:1
-   |
-LL | fn make_dyn_star<'a, T: PointerLike + Debug + 'a>(t: T) -> impl PointerLike + Debug + 'a {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires type-checking `make_dyn_star`...
   --> $DIR/param-env-infer.rs:11:1
    |
diff --git a/tests/ui/impl-trait/auto-trait-leak.stderr b/tests/ui/impl-trait/auto-trait-leak.stderr
index aa4ee75bb75..c0c4cd5013e 100644
--- a/tests/ui/impl-trait/auto-trait-leak.stderr
+++ b/tests/ui/impl-trait/auto-trait-leak.stderr
@@ -4,41 +4,6 @@ error[E0391]: cycle detected when computing type of `cycle1::{opaque#0}`
 LL | fn cycle1() -> impl Clone {
    |                ^^^^^^^^^^
    |
-note: ...which requires borrow-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires promoting constants in MIR for `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires preparing `cycle1` for borrow checking...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires unsafety-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires building MIR for `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires match-checking `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires building THIR for `cycle1`...
-  --> $DIR/auto-trait-leak.rs:12:1
-   |
-LL | fn cycle1() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires type-checking `cycle1`...
   --> $DIR/auto-trait-leak.rs:14:5
    |
@@ -50,41 +15,6 @@ note: ...which requires computing type of `cycle2::{opaque#0}`...
    |
 LL | fn cycle2() -> impl Clone {
    |                ^^^^^^^^^^
-note: ...which requires borrow-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:19:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires promoting constants in MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:19:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires preparing `cycle2` for borrow checking...
-  --> $DIR/auto-trait-leak.rs:19:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires unsafety-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:19:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires building MIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:19:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires match-checking `cycle2`...
-  --> $DIR/auto-trait-leak.rs:19:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires building THIR for `cycle2`...
-  --> $DIR/auto-trait-leak.rs:19:1
-   |
-LL | fn cycle2() -> impl Clone {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires type-checking `cycle2`...
   --> $DIR/auto-trait-leak.rs:20:5
    |
diff --git a/tests/ui/impl-trait/multiple-defining-usages-in-body.rs b/tests/ui/impl-trait/multiple-defining-usages-in-body.rs
index c3a6f09f86d..86661153a0d 100644
--- a/tests/ui/impl-trait/multiple-defining-usages-in-body.rs
+++ b/tests/ui/impl-trait/multiple-defining-usages-in-body.rs
@@ -4,9 +4,9 @@ impl Trait for () {}
 fn foo<T: Trait, U: Trait>() -> impl Trait {
     //~^ WARN function cannot return without recursing [unconditional_recursion]
     let a: T = foo::<T, U>();
-    //~^ ERROR concrete type differs from previous defining opaque type use
     loop {}
     let _: T = foo::<U, T>();
+    //~^ ERROR concrete type differs from previous defining opaque type use
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/multiple-defining-usages-in-body.stderr b/tests/ui/impl-trait/multiple-defining-usages-in-body.stderr
index 06991749bfa..f3c090408b4 100644
--- a/tests/ui/impl-trait/multiple-defining-usages-in-body.stderr
+++ b/tests/ui/impl-trait/multiple-defining-usages-in-body.stderr
@@ -11,15 +11,15 @@ LL |     let a: T = foo::<T, U>();
    = note: `#[warn(unconditional_recursion)]` on by default
 
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/multiple-defining-usages-in-body.rs:6:16
+  --> $DIR/multiple-defining-usages-in-body.rs:8:16
    |
-LL |     let a: T = foo::<T, U>();
-   |                ^^^^^^^^^^^^^ expected `U`, got `T`
+LL |     let _: T = foo::<U, T>();
+   |                ^^^^^^^^^^^^^ expected `T`, got `U`
    |
 note: previous use here
-  --> $DIR/multiple-defining-usages-in-body.rs:9:16
+  --> $DIR/multiple-defining-usages-in-body.rs:6:16
    |
-LL |     let _: T = foo::<U, T>();
+LL |     let a: T = foo::<T, U>();
    |                ^^^^^^^^^^^^^
 
 error: aborting due to previous error; 1 warning emitted
diff --git a/tests/ui/inline-const/elided-lifetime-being-infer-vars.rs b/tests/ui/inline-const/elided-lifetime-being-infer-vars.rs
new file mode 100644
index 00000000000..5661db4a253
--- /dev/null
+++ b/tests/ui/inline-const/elided-lifetime-being-infer-vars.rs
@@ -0,0 +1,11 @@
+// check-pass
+
+#![feature(inline_const)]
+
+fn main() {
+    let _my_usize = const {
+        let a = 10_usize;
+        let b: &'_ usize = &a;
+        *b
+    };
+}
diff --git a/tests/ui/lint/cast_ref_to_mut.rs b/tests/ui/lint/cast_ref_to_mut.rs
new file mode 100644
index 00000000000..745d7070143
--- /dev/null
+++ b/tests/ui/lint/cast_ref_to_mut.rs
@@ -0,0 +1,50 @@
+// check-fail
+
+#![feature(ptr_from_ref)]
+
+extern "C" {
+    // N.B., mutability can be easily incorrect in FFI calls -- as
+    // in C, the default is mutable pointers.
+    fn ffi(c: *mut u8);
+    fn int_ffi(c: *mut i32);
+}
+
+fn main() {
+    let s = String::from("Hello");
+    let a = &s;
+    unsafe {
+        let num = &3i32;
+        let mut_num = &mut 3i32;
+
+        (*(a as *const _ as *mut String)).push_str(" world");
+        //~^ ERROR casting `&T` to `&mut T` is undefined behavior
+        *(a as *const _ as *mut _) = String::from("Replaced");
+        //~^ ERROR casting `&T` to `&mut T` is undefined behavior
+        *(a as *const _ as *mut String) += " world";
+        //~^ ERROR casting `&T` to `&mut T` is undefined behavior
+        let _num = &mut *(num as *const i32 as *mut i32);
+        //~^ ERROR casting `&T` to `&mut T` is undefined behavior
+        let _num = &mut *(num as *const i32).cast_mut();
+        //~^ ERROR casting `&T` to `&mut T` is undefined behavior
+        let _num = *{ num as *const i32 }.cast_mut();
+        //~^ ERROR casting `&T` to `&mut T` is undefined behavior
+        *std::ptr::from_ref(num).cast_mut() += 1;
+        //~^ ERROR casting `&T` to `&mut T` is undefined behavior
+        *std::ptr::from_ref({ num }).cast_mut() += 1;
+        //~^ ERROR casting `&T` to `&mut T` is undefined behavior
+        *{ std::ptr::from_ref(num) }.cast_mut() += 1;
+        //~^ ERROR casting `&T` to `&mut T` is undefined behavior
+        *(std::ptr::from_ref({ num }) as *mut i32) += 1;
+        //~^ ERROR casting `&T` to `&mut T` is undefined behavior
+
+        // Shouldn't be warned against
+        println!("{}", *(num as *const _ as *const i16));
+        println!("{}", *(mut_num as *mut _ as *mut i16));
+        ffi(a.as_ptr() as *mut _);
+        int_ffi(num as *const _ as *mut _);
+        int_ffi(&3 as *const _ as *mut _);
+        let mut value = 3;
+        let value: *const i32 = &mut value;
+        *(value as *const i16 as *mut i16) = 42;
+    }
+}
diff --git a/tests/ui/lint/cast_ref_to_mut.stderr b/tests/ui/lint/cast_ref_to_mut.stderr
new file mode 100644
index 00000000000..baff00d6c04
--- /dev/null
+++ b/tests/ui/lint/cast_ref_to_mut.stderr
@@ -0,0 +1,64 @@
+error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
+  --> $DIR/cast_ref_to_mut.rs:19:9
+   |
+LL |         (*(a as *const _ as *mut String)).push_str(" world");
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[deny(cast_ref_to_mut)]` on by default
+
+error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
+  --> $DIR/cast_ref_to_mut.rs:21:9
+   |
+LL |         *(a as *const _ as *mut _) = String::from("Replaced");
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
+  --> $DIR/cast_ref_to_mut.rs:23:9
+   |
+LL |         *(a as *const _ as *mut String) += " world";
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
+  --> $DIR/cast_ref_to_mut.rs:25:25
+   |
+LL |         let _num = &mut *(num as *const i32 as *mut i32);
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
+  --> $DIR/cast_ref_to_mut.rs:27:25
+   |
+LL |         let _num = &mut *(num as *const i32).cast_mut();
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
+  --> $DIR/cast_ref_to_mut.rs:29:20
+   |
+LL |         let _num = *{ num as *const i32 }.cast_mut();
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
+  --> $DIR/cast_ref_to_mut.rs:31:9
+   |
+LL |         *std::ptr::from_ref(num).cast_mut() += 1;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
+  --> $DIR/cast_ref_to_mut.rs:33:9
+   |
+LL |         *std::ptr::from_ref({ num }).cast_mut() += 1;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
+  --> $DIR/cast_ref_to_mut.rs:35:9
+   |
+LL |         *{ std::ptr::from_ref(num) }.cast_mut() += 1;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
+  --> $DIR/cast_ref_to_mut.rs:37:9
+   |
+LL |         *(std::ptr::from_ref({ num }) as *mut i32) += 1;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 10 previous errors
+
diff --git a/tests/ui/loops/dont-suggest-break-thru-item.rs b/tests/ui/loops/dont-suggest-break-thru-item.rs
new file mode 100644
index 00000000000..b46ba89e81d
--- /dev/null
+++ b/tests/ui/loops/dont-suggest-break-thru-item.rs
@@ -0,0 +1,55 @@
+// edition:2021
+
+#![feature(inline_const)]
+
+fn closure() {
+    loop {
+        let closure = || {
+            if true {
+                Err(1)
+                //~^ ERROR mismatched types
+            }
+
+            Ok(())
+        };
+    }
+}
+
+fn async_block() {
+    loop {
+        let fut = async {
+            if true {
+                Err(1)
+                //~^ ERROR mismatched types
+            }
+
+            Ok(())
+        };
+    }
+}
+
+fn fn_item() {
+    let _ = loop {
+        fn foo() -> Result<(), ()> {
+            if true {
+                Err(1)
+                //~^ ERROR mismatched types
+            }
+            Err(())
+        }
+    };
+}
+
+fn const_block() {
+    let _ = loop {
+        const {
+            if true {
+                Err(1)
+                //~^ ERROR mismatched types
+            }
+            Err(())
+        };
+    };
+}
+
+fn main() {}
diff --git a/tests/ui/loops/dont-suggest-break-thru-item.stderr b/tests/ui/loops/dont-suggest-break-thru-item.stderr
new file mode 100644
index 00000000000..4fce4715119
--- /dev/null
+++ b/tests/ui/loops/dont-suggest-break-thru-item.stderr
@@ -0,0 +1,55 @@
+error[E0308]: mismatched types
+  --> $DIR/dont-suggest-break-thru-item.rs:9:17
+   |
+LL | /             if true {
+LL | |                 Err(1)
+   | |                 ^^^^^^ expected `()`, found `Result<_, {integer}>`
+LL | |
+LL | |             }
+   | |_____________- expected this to be `()`
+   |
+   = note: expected unit type `()`
+                   found enum `Result<_, {integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/dont-suggest-break-thru-item.rs:22:17
+   |
+LL | /             if true {
+LL | |                 Err(1)
+   | |                 ^^^^^^ expected `()`, found `Result<_, {integer}>`
+LL | |
+LL | |             }
+   | |_____________- expected this to be `()`
+   |
+   = note: expected unit type `()`
+                   found enum `Result<_, {integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/dont-suggest-break-thru-item.rs:35:17
+   |
+LL | /             if true {
+LL | |                 Err(1)
+   | |                 ^^^^^^ expected `()`, found `Result<_, {integer}>`
+LL | |
+LL | |             }
+   | |_____________- expected this to be `()`
+   |
+   = note: expected unit type `()`
+                   found enum `Result<_, {integer}>`
+
+error[E0308]: mismatched types
+  --> $DIR/dont-suggest-break-thru-item.rs:47:17
+   |
+LL | /             if true {
+LL | |                 Err(1)
+   | |                 ^^^^^^ expected `()`, found `Result<_, {integer}>`
+LL | |
+LL | |             }
+   | |_____________- expected this to be `()`
+   |
+   = note: expected unit type `()`
+                   found enum `Result<_, {integer}>`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/match/issue-70972-dyn-trait.rs b/tests/ui/match/issue-70972-dyn-trait.rs
index 97d161c59ec..df28c474ab0 100644
--- a/tests/ui/match/issue-70972-dyn-trait.rs
+++ b/tests/ui/match/issue-70972-dyn-trait.rs
@@ -4,7 +4,7 @@ fn main() {
     let a: &dyn Send = &7u32;
     match a {
         F => panic!(),
-        //~^ ERROR `&dyn Send` cannot be used in patterns
+        //~^ ERROR `dyn Send` cannot be used in patterns
         _ => {}
     }
 }
diff --git a/tests/ui/match/issue-70972-dyn-trait.stderr b/tests/ui/match/issue-70972-dyn-trait.stderr
index 7581070ebc1..f4dc910c34a 100644
--- a/tests/ui/match/issue-70972-dyn-trait.stderr
+++ b/tests/ui/match/issue-70972-dyn-trait.stderr
@@ -1,4 +1,4 @@
-error: `&dyn Send` cannot be used in patterns
+error: `dyn Send` cannot be used in patterns
   --> $DIR/issue-70972-dyn-trait.rs:6:9
    |
 LL |         F => panic!(),
diff --git a/tests/ui/numbers-arithmetic/issue-8460-const.noopt.stderr b/tests/ui/numbers-arithmetic/issue-8460-const.noopt.stderr
index c4abcb78411..2fba94d0740 100644
--- a/tests/ui/numbers-arithmetic/issue-8460-const.noopt.stderr
+++ b/tests/ui/numbers-arithmetic/issue-8460-const.noopt.stderr
@@ -76,37 +76,37 @@ error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:35:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^^ attempt to compute the remainder of `isize::MIN % -1_isize`, which would overflow
+   |                                    ^^^^^^^^^^^^^^^ attempt to compute `isize::MIN % -1_isize`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:37:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^ attempt to compute the remainder of `i8::MIN % -1_i8`, which would overflow
+   |                                    ^^^^^^^^^^^^ attempt to compute `i8::MIN % -1_i8`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:39:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i16::MIN % -1_i16`, which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute `i16::MIN % -1_i16`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:41:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute `i32::MIN % -1_i32`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:43:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute `i64::MIN % -1_i64`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:45:36
    |
 LL |     assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^ attempt to compute the remainder of `i128::MIN % -1_i128`, which would overflow
+   |                                    ^^^^^^^^^^^^^^ attempt to compute `i128::MIN % -1_i128`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:47:36
diff --git a/tests/ui/numbers-arithmetic/issue-8460-const.opt.stderr b/tests/ui/numbers-arithmetic/issue-8460-const.opt.stderr
index c4abcb78411..2fba94d0740 100644
--- a/tests/ui/numbers-arithmetic/issue-8460-const.opt.stderr
+++ b/tests/ui/numbers-arithmetic/issue-8460-const.opt.stderr
@@ -76,37 +76,37 @@ error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:35:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^^ attempt to compute the remainder of `isize::MIN % -1_isize`, which would overflow
+   |                                    ^^^^^^^^^^^^^^^ attempt to compute `isize::MIN % -1_isize`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:37:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^ attempt to compute the remainder of `i8::MIN % -1_i8`, which would overflow
+   |                                    ^^^^^^^^^^^^ attempt to compute `i8::MIN % -1_i8`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:39:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i16::MIN % -1_i16`, which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute `i16::MIN % -1_i16`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:41:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute `i32::MIN % -1_i32`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:43:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute `i64::MIN % -1_i64`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:45:36
    |
 LL |     assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^ attempt to compute the remainder of `i128::MIN % -1_i128`, which would overflow
+   |                                    ^^^^^^^^^^^^^^ attempt to compute `i128::MIN % -1_i128`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:47:36
diff --git a/tests/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr b/tests/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr
index c4abcb78411..2fba94d0740 100644
--- a/tests/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr
+++ b/tests/ui/numbers-arithmetic/issue-8460-const.opt_with_overflow_checks.stderr
@@ -76,37 +76,37 @@ error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:35:36
    |
 LL |     assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^^ attempt to compute the remainder of `isize::MIN % -1_isize`, which would overflow
+   |                                    ^^^^^^^^^^^^^^^ attempt to compute `isize::MIN % -1_isize`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:37:36
    |
 LL |     assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^ attempt to compute the remainder of `i8::MIN % -1_i8`, which would overflow
+   |                                    ^^^^^^^^^^^^ attempt to compute `i8::MIN % -1_i8`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:39:36
    |
 LL |     assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i16::MIN % -1_i16`, which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute `i16::MIN % -1_i16`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:41:36
    |
 LL |     assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute `i32::MIN % -1_i32`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:43:36
    |
 LL |     assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow
+   |                                    ^^^^^^^^^^^^^ attempt to compute `i64::MIN % -1_i64`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:45:36
    |
 LL |     assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err());
-   |                                    ^^^^^^^^^^^^^^ attempt to compute the remainder of `i128::MIN % -1_i128`, which would overflow
+   |                                    ^^^^^^^^^^^^^^ attempt to compute `i128::MIN % -1_i128`, which would overflow
 
 error: this operation will panic at runtime
   --> $DIR/issue-8460-const.rs:47:36
diff --git a/tests/ui/pattern/issue-72565.rs b/tests/ui/pattern/issue-72565.rs
index 1e262fd5067..21edb26de08 100644
--- a/tests/ui/pattern/issue-72565.rs
+++ b/tests/ui/pattern/issue-72565.rs
@@ -3,6 +3,6 @@ const F: &'static dyn PartialEq<u32> = &7u32;
 fn main() {
     let a: &dyn PartialEq<u32> = &7u32;
     match a {
-        F => panic!(), //~ ERROR: `&dyn PartialEq<u32>` cannot be used in patterns
+        F => panic!(), //~ ERROR: `dyn PartialEq<u32>` cannot be used in patterns
     }
 }
diff --git a/tests/ui/pattern/issue-72565.stderr b/tests/ui/pattern/issue-72565.stderr
index 2f82616b277..0519720694d 100644
--- a/tests/ui/pattern/issue-72565.stderr
+++ b/tests/ui/pattern/issue-72565.stderr
@@ -1,4 +1,4 @@
-error: `&dyn PartialEq<u32>` cannot be used in patterns
+error: `dyn PartialEq<u32>` cannot be used in patterns
   --> $DIR/issue-72565.rs:6:9
    |
 LL |         F => panic!(),
diff --git a/tests/ui/statics/uninhabited-static.stderr b/tests/ui/statics/uninhabited-static.stderr
index 35fdcae6a59..9260930473f 100644
--- a/tests/ui/statics/uninhabited-static.stderr
+++ b/tests/ui/statics/uninhabited-static.stderr
@@ -47,7 +47,7 @@ error[E0080]: could not evaluate static initializer
   --> $DIR/uninhabited-static.rs:12:31
    |
 LL | static VOID2: Void = unsafe { std::mem::transmute(()) };
-   |                               ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a value of uninhabited type Void
+   |                               ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a value of uninhabited type `Void`
 
 warning: the type `Void` does not permit zero-initialization
   --> $DIR/uninhabited-static.rs:12:31
@@ -66,7 +66,7 @@ error[E0080]: could not evaluate static initializer
   --> $DIR/uninhabited-static.rs:16:32
    |
 LL | static NEVER2: Void = unsafe { std::mem::transmute(()) };
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a value of uninhabited type Void
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a value of uninhabited type `Void`
 
 warning: the type `Void` does not permit zero-initialization
   --> $DIR/uninhabited-static.rs:16:32
diff --git a/tests/ui/suggestions/issue-88696.rs b/tests/ui/suggestions/issue-88696.rs
new file mode 100644
index 00000000000..745fdef1546
--- /dev/null
+++ b/tests/ui/suggestions/issue-88696.rs
@@ -0,0 +1,14 @@
+// This test case should ensure that miniz_oxide isn't
+// suggested, since it's not a direct dependency.
+
+fn a() -> Result<u64, i32> {
+    Err(1)
+}
+
+fn b() -> Result<u32, i32> {
+    a().into() //~ERROR [E0277]
+}
+
+fn main() {
+    let _ = dbg!(b());
+}
diff --git a/tests/ui/suggestions/issue-88696.stderr b/tests/ui/suggestions/issue-88696.stderr
new file mode 100644
index 00000000000..4947269d759
--- /dev/null
+++ b/tests/ui/suggestions/issue-88696.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the trait bound `Result<u32, i32>: From<Result<u64, i32>>` is not satisfied
+  --> $DIR/issue-88696.rs:9:9
+   |
+LL |     a().into()
+   |         ^^^^ the trait `From<Result<u64, i32>>` is not implemented for `Result<u32, i32>`
+   |
+   = note: required for `Result<u64, i32>` to implement `Into<Result<u32, i32>>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/track-diagnostics/track6.stderr b/tests/ui/track-diagnostics/track6.stderr
index 89438aea9ad..583b02555b4 100644
--- a/tests/ui/track-diagnostics/track6.stderr
+++ b/tests/ui/track-diagnostics/track6.stderr
@@ -3,7 +3,7 @@ error[E0658]: specialization is unstable
    |
 LL |     default fn bar() {}
    |     ^^^^^^^^^^^^^^^^^^^
--Ztrack-diagnostics: created at $COMPILER_DIR/rustc_session/src/parse.rs:LL:CC
+-Ztrack-diagnostics: created at compiler/rustc_ast_passes/src/feature_gate.rs:LL:CC
    |
    = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
    = help: add `#![feature(specialization)]` to the crate attributes to enable
diff --git a/tests/ui/traits/new-solver/dont-remap-tait-substs.rs b/tests/ui/traits/new-solver/dont-remap-tait-substs.rs
new file mode 100644
index 00000000000..028222f4e6d
--- /dev/null
+++ b/tests/ui/traits/new-solver/dont-remap-tait-substs.rs
@@ -0,0 +1,19 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+// Makes sure we don't prepopulate the MIR typeck of `define`
+// with `Foo<T, U> = T`, but instead, `Foo<B, A> = B`, so that
+// the param-env predicates actually apply.
+
+#![feature(type_alias_impl_trait)]
+
+type Foo<T: Send, U> = impl NeedsSend<T>;
+
+trait NeedsSend<T> {}
+impl<T: Send> NeedsSend<T> for T {}
+
+fn define<A, B: Send>(a: A, b: B) {
+    let y: Option<Foo<B, A>> = Some(b);
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/cross_inference.rs b/tests/ui/type-alias-impl-trait/cross_inference.rs
index dafaf40a69d..07f3dd1997b 100644
--- a/tests/ui/type-alias-impl-trait/cross_inference.rs
+++ b/tests/ui/type-alias-impl-trait/cross_inference.rs
@@ -1,3 +1,5 @@
+// revisions: current next
+//[next] compile-flags: -Ztrait-solver=next
 // check-pass
 
 #![feature(type_alias_impl_trait)]
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs
index 9ae2c34b935..da845e86147 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs
@@ -8,7 +8,6 @@ type X<A, B> = impl Into<&'static A>;
 
 fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
     //~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied
-    //~| ERROR concrete type differs from previous defining opaque type use
     (a, a)
 }
 
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
index 0d24d42ba62..66a6b0bbf74 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
@@ -10,15 +10,6 @@ help: consider introducing a `where` clause, but there might be an alternative b
 LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) where &'static B: From<&A> {
    |                                                                ++++++++++++++++++++++++++
 
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/multiple-def-uses-in-one-fn.rs:9:45
-   |
-LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
-   |                                             ^^^^^^^^^^^^^^^^^^
-   |                                             |
-   |                                             expected `&B`, got `&A`
-   |                                             this expression supplies two conflicting concrete types for the same opaque type
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/triagebot.toml b/triagebot.toml
index c160c83cc95..b1f4e9c77fb 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -387,6 +387,10 @@ cc = [
 message = "Some changes occurred in HTML/CSS themes."
 cc = ["@GuillaumeGomez"]
 
+[mentions."tests/rustdoc-gui/"]
+message = "Some changes occurred in GUI tests."
+cc = ["@GuillaumeGomez"]
+
 [mentions."src/librustdoc/html/static/css/themes/ayu.css"]
 message = "A change occurred in the Ayu theme."
 cc = ["@Cldfire"]