about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock24
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs4
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/find_use.rs7
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs14
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/invalidation.rs8
-rw-r--r--compiler/rustc_borrowck/src/lib.rs10
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs65
-rw-r--r--compiler/rustc_borrowck/src/type_check/relate_tys.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs8
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs29
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs17
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs25
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs42
-rw-r--r--compiler/rustc_codegen_llvm/src/type_.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs11
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/analyze.rs10
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs227
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs10
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs10
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs29
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs14
-rw-r--r--compiler/rustc_const_eval/src/interpret/mod.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs34
-rw-r--r--compiler/rustc_const_eval/src/lib.rs1
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs4
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/promote_consts.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs53
-rw-r--r--compiler/rustc_data_structures/src/lib.rs6
-rw-r--r--compiler/rustc_data_structures/src/memmap.rs10
-rw-r--r--compiler/rustc_data_structures/src/owned_slice.rs118
-rw-r--r--compiler/rustc_data_structures/src/owned_slice/tests.rs74
-rw-r--r--compiler/rustc_data_structures/src/owning_ref/LICENSE21
-rw-r--r--compiler/rustc_data_structures/src/owning_ref/mod.rs1211
-rw-r--r--compiler/rustc_data_structures/src/owning_ref/tests.rs711
-rw-r--r--compiler/rustc_data_structures/src/sync.rs33
-rw-r--r--compiler/rustc_feature/src/active.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/generator_interior/mod.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/intrinsicck.rs7
-rw-r--r--compiler/rustc_infer/messages.ftl4
-rw-r--r--compiler/rustc_infer/src/errors/note_and_explain.rs5
-rw-r--r--compiler/rustc_infer/src/infer/canonical/canonicalizer.rs2
-rw-r--r--compiler/rustc_infer/src/infer/canonical/mod.rs12
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs10
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs5
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs20
-rw-r--r--compiler/rustc_infer/src/infer/higher_ranked/mod.rs14
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs16
-rw-r--r--compiler/rustc_infer/src/infer/nll_relate/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/region_constraints/leak_check.rs4
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp77
-rw-r--r--compiler/rustc_macros/Cargo.toml4
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs157
-rw-r--r--compiler/rustc_macros/src/diagnostics/error.rs55
-rw-r--r--compiler/rustc_macros/src/diagnostics/subdiagnostic.rs79
-rw-r--r--compiler/rustc_macros/src/diagnostics/utils.rs222
-rw-r--r--compiler/rustc_macros/src/hash_stable.rs45
-rw-r--r--compiler/rustc_macros/src/newtype.rs10
-rw-r--r--compiler/rustc_macros/src/query.rs8
-rw-r--r--compiler/rustc_macros/src/type_foldable.rs27
-rw-r--r--compiler/rustc_macros/src/type_visitable.rs30
-rw-r--r--compiler/rustc_metadata/src/lib.rs2
-rw-r--r--compiler/rustc_metadata/src/locator.rs22
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs6
-rw-r--r--compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs14
-rw-r--r--compiler/rustc_middle/src/infer/canonical.rs10
-rw-r--r--compiler/rustc_middle/src/mir/patch.rs58
-rw-r--r--compiler/rustc_middle/src/mir/query.rs6
-rw-r--r--compiler/rustc_middle/src/mir/spanview.rs2
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs56
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs177
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs8
-rw-r--r--compiler/rustc_middle/src/ty/context.rs12
-rw-r--r--compiler/rustc_middle/src/ty/fold.rs8
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs95
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs6
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs21
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs6
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs43
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse/instruction.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs8
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs13
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs36
-rw-r--r--compiler/rustc_mir_build/src/lints.rs8
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs20
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/direction.rs16
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/tests.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/builder.rs6
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs2
-rw-r--r--compiler/rustc_mir_transform/src/abort_unwinding_calls.rs30
-rw-r--r--compiler/rustc_mir_transform/src/add_call_guards.rs5
-rw-r--r--compiler/rustc_mir_transform/src/check_alignment.rs2
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs2
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs10
-rw-r--r--compiler/rustc_mir_transform/src/const_prop_lint.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coverage/debug.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coverage/graph.rs4
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs2
-rw-r--r--compiler/rustc_mir_transform/src/coverage/tests.rs2
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs6
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs4
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs52
-rw-r--r--compiler/rustc_mir_transform/src/function_item_references.rs2
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs26
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs60
-rw-r--r--compiler/rustc_mir_transform/src/lib.rs4
-rw-r--r--compiler/rustc_mir_transform/src/lower_slice_len.rs1
-rw-r--r--compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs6
-rw-r--r--compiler/rustc_mir_transform/src/separate_const_switch.rs4
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs26
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs12
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs4
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs20
-rw-r--r--compiler/rustc_resolve/src/late.rs32
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs33
-rw-r--r--compiler/rustc_trait_selection/src/solve/canonicalize.rs18
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs28
-rw-r--r--compiler/rustc_traits/src/chalk/db.rs2
-rw-r--r--compiler/rustc_traits/src/chalk/lowering.rs50
-rw-r--r--config.example.toml2
-rw-r--r--library/core/src/convert/mod.rs2
-rw-r--r--library/core/src/num/shells/u16.rs2
-rw-r--r--library/core/src/option.rs4
-rw-r--r--library/core/src/result.rs7
-rw-r--r--library/std/src/io/buffered/bufwriter.rs2
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/net/tcp.rs2
-rw-r--r--library/std/src/sys/common/thread_local/os_local.rs4
-rw-r--r--library/std/src/sys/windows/fs.rs34
-rw-r--r--src/bootstrap/Cargo.lock11
-rw-r--r--src/bootstrap/Cargo.toml3
-rw-r--r--src/bootstrap/config.rs21
-rw-r--r--src/bootstrap/config/tests.rs65
-rw-r--r--src/bootstrap/download.rs64
-rw-r--r--src/bootstrap/test.rs2
-rw-r--r--src/bootstrap/util.rs99
-rw-r--r--src/doc/rustdoc/src/unstable-features.md9
-rw-r--r--src/doc/rustdoc/src/write-documentation/what-to-include.md4
-rw-r--r--src/librustdoc/html/format.rs4
-rw-r--r--src/librustdoc/html/render/mod.rs358
-rw-r--r--src/librustdoc/html/render/print_item.rs680
-rw-r--r--src/librustdoc/html/sources.rs6
-rw-r--r--src/librustdoc/html/static/js/main.js10
-rw-r--r--src/librustdoc/html/static/js/settings.js8
-rw-r--r--src/librustdoc/html/static/js/storage.js20
-rw-r--r--src/librustdoc/html/templates/item_union.html23
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs6
-rw-r--r--src/tools/miri/src/helpers.rs2
-rw-r--r--src/tools/miri/src/lib.rs1
-rw-r--r--src/tools/miri/src/machine.rs8
-rw-r--r--src/tools/miri/src/shims/foreign_items.rs2
-rw-r--r--src/tools/miri/src/shims/intrinsics/mod.rs2
-rw-r--r--src/tools/miri/src/shims/mod.rs4
-rw-r--r--src/tools/miri/src/shims/panic.rs25
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs4
-rw-r--r--src/tools/miri/tests/fail/terminate-terminator.rs27
-rw-r--r--src/tools/miri/tests/fail/terminate-terminator.stderr27
-rw-r--r--src/tools/miri/tests/fail/unwind-action-terminate.rs (renamed from src/tools/miri/tests/fail/abort-terminator.rs)2
-rw-r--r--src/tools/miri/tests/fail/unwind-action-terminate.stderr (renamed from src/tools/miri/tests/fail/abort-terminator.stderr)12
-rw-r--r--tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir2
-rw-r--r--tests/mir-opt/array_index_is_temporary.rs1
-rw-r--r--tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir6
-rw-r--r--tests/mir-opt/basic_assignment.main.ElaborateDrops.diff10
-rw-r--r--tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir6
-rw-r--r--tests/mir-opt/box_expr.main.ElaborateDrops.before.mir6
-rw-r--r--tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir16
-rw-r--r--tests/mir-opt/building/enum_cast.droppy.built.after.mir2
-rw-r--r--tests/mir-opt/building/issue_49232.main.built.after.mir2
-rw-r--r--tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir6
-rw-r--r--tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir6
-rw-r--r--tests/mir-opt/combine_array_len.rs1
-rw-r--r--tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff2
-rw-r--r--tests/mir-opt/combine_transmutes.adt_transmutes.InstCombine.diff2
-rw-r--r--tests/mir-opt/combine_transmutes.identity_transmutes.InstCombine.diff4
-rw-r--r--tests/mir-opt/const_prop/aggregate.main.ConstProp.diff2
-rw-r--r--tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir2
-rw-r--r--tests/mir-opt/const_prop/aggregate.rs1
-rw-r--r--tests/mir-opt/const_prop/array_index.rs1
-rw-r--r--tests/mir-opt/const_prop/bad_op_div_by_zero.rs1
-rw-r--r--tests/mir-opt/const_prop/bad_op_mod_by_zero.rs1
-rw-r--r--tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff2
-rw-r--r--tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff2
-rw-r--r--tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs1
-rw-r--r--tests/mir-opt/const_prop/checked_add.rs1
-rw-r--r--tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff4
-rw-r--r--tests/mir-opt/const_prop/const_prop_fails_gracefully.rs1
-rw-r--r--tests/mir-opt/const_prop/control_flow_simplification.rs1
-rw-r--r--tests/mir-opt/const_prop/indirect.rs1
-rw-r--r--tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.diff2
-rw-r--r--tests/mir-opt/const_prop/inherit_overflow.rs1
-rw-r--r--tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff2
-rw-r--r--tests/mir-opt/const_prop/issue_66971.rs1
-rw-r--r--tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff2
-rw-r--r--tests/mir-opt/const_prop/issue_67019.rs1
-rw-r--r--tests/mir-opt/const_prop/large_array_index.rs1
-rw-r--r--tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff2
-rw-r--r--tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs1
-rw-r--r--tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff2
-rw-r--r--tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs1
-rw-r--r--tests/mir-opt/const_prop/optimizes_into_variable.rs1
-rw-r--r--tests/mir-opt/const_prop/repeat.rs1
-rw-r--r--tests/mir-opt/const_prop/return_place.rs1
-rw-r--r--tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff2
-rw-r--r--tests/mir-opt/const_prop/scalar_literal_propagation.rs1
-rw-r--r--tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff2
-rw-r--r--tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff2
-rw-r--r--tests/mir-opt/const_prop/slice_len.rs1
-rw-r--r--tests/mir-opt/const_prop/switch_int.main.ConstProp.diff4
-rw-r--r--tests/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff4
-rw-r--r--tests/mir-opt/const_prop/switch_int.rs1
-rw-r--r--tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff2
-rw-r--r--tests/mir-opt/const_prop/tuple_literal_propagation.rs1
-rw-r--r--tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.diff4
-rw-r--r--tests/mir-opt/copy-prop/borrowed_local.rs1
-rw-r--r--tests/mir-opt/copy-prop/branch.foo.CopyProp.diff6
-rw-r--r--tests/mir-opt/copy-prop/branch.rs1
-rw-r--r--tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.diff2
-rw-r--r--tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.diff2
-rw-r--r--tests/mir-opt/copy-prop/copy_propagation_arg.rs1
-rw-r--r--tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.diff4
-rw-r--r--tests/mir-opt/copy-prop/custom_move_arg.rs1
-rw-r--r--tests/mir-opt/copy-prop/cycle.main.CopyProp.diff4
-rw-r--r--tests/mir-opt/copy-prop/cycle.rs1
-rw-r--r--tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir2
-rw-r--r--tests/mir-opt/copy-prop/dead_stores_79191.rs1
-rw-r--r--tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir2
-rw-r--r--tests/mir-opt/copy-prop/dead_stores_better.rs1
-rw-r--r--tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff6
-rw-r--r--tests/mir-opt/copy-prop/issue_107511.rs1
-rw-r--r--tests/mir-opt/copy-prop/move_arg.f.CopyProp.diff2
-rw-r--r--tests/mir-opt/copy-prop/move_arg.rs1
-rw-r--r--tests/mir-opt/copy-prop/move_projection.f.CopyProp.diff4
-rw-r--r--tests/mir-opt/copy-prop/move_projection.rs1
-rw-r--r--tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.diff2
-rw-r--r--tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.diff2
-rw-r--r--tests/mir-opt/copy-prop/reborrow.remut.CopyProp.diff2
-rw-r--r--tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.diff2
-rw-r--r--tests/mir-opt/copy-prop/reborrow.rs1
-rw-r--r--tests/mir-opt/dataflow-const-prop/checked.rs1
-rw-r--r--tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff2
-rw-r--r--tests/mir-opt/dataflow-const-prop/inherit_overflow.rs1
-rw-r--r--tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff4
-rw-r--r--tests/mir-opt/dataflow-const-prop/ref_without_sb.rs1
-rw-r--r--tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff2
-rw-r--r--tests/mir-opt/dataflow-const-prop/sibling_ptr.rs1
-rw-r--r--tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff2
-rw-r--r--tests/mir-opt/dataflow-const-prop/terminator.rs1
-rw-r--r--tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff2
-rw-r--r--tests/mir-opt/dead-store-elimination/cycle.rs1
-rw-r--r--tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff2
-rw-r--r--tests/mir-opt/deduplicate_blocks.rs1
-rw-r--r--tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir8
-rw-r--r--tests/mir-opt/derefer_inline_test.main.Derefer.diff2
-rw-r--r--tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff6
-rw-r--r--tests/mir-opt/dest-prop/branch.rs1
-rw-r--r--tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff2
-rw-r--r--tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff2
-rw-r--r--tests/mir-opt/dest-prop/copy_propagation_arg.rs1
-rw-r--r--tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff4
-rw-r--r--tests/mir-opt/dest-prop/cycle.rs1
-rw-r--r--tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.mir2
-rw-r--r--tests/mir-opt/dest-prop/dead_stores_79191.rs1
-rw-r--r--tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir2
-rw-r--r--tests/mir-opt/dest-prop/dead_stores_better.rs1
-rw-r--r--tests/mir-opt/dest-prop/simple.rs1
-rw-r--r--tests/mir-opt/dest-prop/union.main.DestinationPropagation.diff4
-rw-r--r--tests/mir-opt/dest-prop/union.rs1
-rw-r--r--tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.diff4
-rw-r--r--tests/mir-opt/dest-prop/unreachable.rs1
-rw-r--r--tests/mir-opt/div_overflow.rs1
-rw-r--r--tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff2
-rw-r--r--tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff8
-rw-r--r--tests/mir-opt/funky_arms.rs1
-rw-r--r--tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir4
-rw-r--r--tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir2
-rw-r--r--tests/mir-opt/inline/asm_unwind.main.Inline.diff2
-rw-r--r--tests/mir-opt/inline/cycle.f.Inline.diff2
-rw-r--r--tests/mir-opt/inline/cycle.g.Inline.diff2
-rw-r--r--tests/mir-opt/inline/cycle.main.Inline.diff2
-rw-r--r--tests/mir-opt/inline/dyn_trait.get_query.Inline.diff24
-rw-r--r--tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff2
-rw-r--r--tests/mir-opt/inline/dyn_trait.rs1
-rw-r--r--tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff10
-rw-r--r--tests/mir-opt/inline/exponential_runtime.main.Inline.diff50
-rw-r--r--tests/mir-opt/inline/exponential_runtime.rs1
-rw-r--r--tests/mir-opt/inline/inline_cycle.one.Inline.diff12
-rw-r--r--tests/mir-opt/inline/inline_cycle.rs1
-rw-r--r--tests/mir-opt/inline/inline_cycle.two.Inline.diff20
-rw-r--r--tests/mir-opt/inline/inline_cycle_generic.main.Inline.diff10
-rw-r--r--tests/mir-opt/inline/inline_cycle_generic.rs1
-rw-r--r--tests/mir-opt/inline/inline_diverging.h.Inline.diff4
-rw-r--r--tests/mir-opt/inline/inline_instruction_set.default.Inline.diff10
-rw-r--r--tests/mir-opt/inline/inline_instruction_set.t32.Inline.diff10
-rw-r--r--tests/mir-opt/inline/inline_into_box_place.main.Inline.diff2
-rw-r--r--tests/mir-opt/inline/inline_options.main.Inline.after.mir22
-rw-r--r--tests/mir-opt/inline/inline_options.rs1
-rw-r--r--tests/mir-opt/inline/inline_specialization.main.Inline.diff6
-rw-r--r--tests/mir-opt/inline/inline_specialization.rs1
-rw-r--r--tests/mir-opt/inline/inline_trait_method.rs1
-rw-r--r--tests/mir-opt/inline/inline_trait_method.test.Inline.after.mir2
-rw-r--r--tests/mir-opt/inline/inline_trait_method_2.rs1
-rw-r--r--tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir8
-rw-r--r--tests/mir-opt/inline/issue_106141.outer.Inline.diff38
-rw-r--r--tests/mir-opt/inline/issue_106141.rs1
-rw-r--r--tests/mir-opt/inline/issue_78442.bar.Inline.diff4
-rw-r--r--tests/mir-opt/inline/issue_78442.bar.RevealAll.diff2
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.rs1
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.Inline.diff125
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shl_unsigned_smaller.PreCodegen.after.mir118
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.Inline.diff125
-rw-r--r--tests/mir-opt/inline/unchecked_shifts.unchecked_shr_signed_smaller.PreCodegen.after.mir118
-rw-r--r--tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff2
-rw-r--r--tests/mir-opt/intrinsic_asserts.generic.InstCombine.diff6
-rw-r--r--tests/mir-opt/intrinsic_asserts.panics.InstCombine.diff12
-rw-r--r--tests/mir-opt/intrinsic_asserts.removable.InstCombine.diff6
-rw-r--r--tests/mir-opt/issue_101973.inner.ConstProp.diff28
-rw-r--r--tests/mir-opt/issue_101973.rs1
-rw-r--r--tests/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir2
-rw-r--r--tests/mir-opt/issue_41110.main.ElaborateDrops.diff8
-rw-r--r--tests/mir-opt/issue_41110.test.ElaborateDrops.diff18
-rw-r--r--tests/mir-opt/issue_41888.main.ElaborateDrops.diff38
-rw-r--r--tests/mir-opt/issue_62289.test.ElaborateDrops.before.mir4
-rw-r--r--tests/mir-opt/issue_76432.rs1
-rw-r--r--tests/mir-opt/issue_91633.bar.built.after.mir2
-rw-r--r--tests/mir-opt/issue_91633.foo.built.after.mir2
-rw-r--r--tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir6
-rw-r--r--tests/mir-opt/issues/issue_59352.rs1
-rw-r--r--tests/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir2
-rw-r--r--tests/mir-opt/lower_array_len.rs1
-rw-r--r--tests/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff8
-rw-r--r--tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.diff4
-rw-r--r--tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.size_of.LowerIntrinsics.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff6
-rw-r--r--tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff6
-rw-r--r--tests/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir2
-rw-r--r--tests/mir-opt/lower_intrinsics_e2e.f_unit.PreCodegen.after.mir2
-rw-r--r--tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff2
-rw-r--r--tests/mir-opt/lower_slice_len.rs1
-rw-r--r--tests/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff2
-rw-r--r--tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir2
-rw-r--r--tests/mir-opt/nrvo_simple.rs1
-rw-r--r--tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir2
-rw-r--r--tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff4
-rw-r--r--tests/mir-opt/remove_storage_markers.rs1
-rw-r--r--tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir4
-rw-r--r--tests/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff4
-rw-r--r--tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff2
-rw-r--r--tests/mir-opt/simplify_if.rs1
-rw-r--r--tests/mir-opt/simplify_locals_fixedpoint.rs1
-rw-r--r--tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff4
-rw-r--r--tests/mir-opt/simplify_locals_removes_unused_consts.rs1
-rw-r--r--tests/mir-opt/simplify_match.main.ConstProp.diff2
-rw-r--r--tests/mir-opt/simplify_match.rs1
-rw-r--r--tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir2
-rw-r--r--tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff16
-rw-r--r--tests/mir-opt/sroa/structs.dropping.ScalarReplacementOfAggregates.diff6
-rw-r--r--tests/mir-opt/sroa/structs.escaping.ScalarReplacementOfAggregates.diff4
-rw-r--r--tests/mir-opt/unreachable.main.UnreachablePropagation.diff2
-rw-r--r--tests/mir-opt/unreachable.rs1
-rw-r--r--tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff4
-rw-r--r--tests/mir-opt/unreachable_diverging.rs1
-rw-r--r--tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir2
-rw-r--r--tests/mir-opt/while_storage.rs1
-rw-r--r--tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir4
-rw-r--r--tests/run-make/coverage-reports/expected_show_coverage.abort.txt2
-rw-r--r--tests/run-make/coverage/abort.rs2
-rw-r--r--tests/rustdoc-gui/go-to-collapsed-elem.goml33
-rw-r--r--tests/rustdoc-gui/theme-defaults.goml24
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs44
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr313
-rw-r--r--tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs43
-rw-r--r--tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr288
-rw-r--r--tests/ui/const-generics/defaults/doesnt_infer.stderr2
-rw-r--r--tests/ui/const-generics/transmute-fail.rs35
-rw-r--r--tests/ui/const-generics/transmute-fail.stderr52
-rw-r--r--tests/ui/const-generics/transmute.rs83
-rw-r--r--tests/ui/const-generics/transmute_no_gate.rs91
-rw-r--r--tests/ui/const-generics/transmute_no_gate.stderr84
-rw-r--r--tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr2
-rw-r--r--tests/ui/inference/issue-83606.stderr2
-rw-r--r--tests/ui/inference/need_type_info/concrete-impl.rs3
-rw-r--r--tests/ui/inference/need_type_info/concrete-impl.stderr9
-rw-r--r--tests/ui/inference/need_type_info/issue-109905.rs25
-rw-r--r--tests/ui/inference/need_type_info/issue-109905.stderr15
-rw-r--r--tests/ui/issues/issue-98299.stderr2
-rw-r--r--tests/ui/nll/closure-requirements/escape-argument-callee.stderr2
-rw-r--r--tests/ui/nll/closure-requirements/escape-argument.stderr2
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr2
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr2
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr4
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr2
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr2
-rw-r--r--tests/ui/nll/closure-requirements/propagate-approximated-val.stderr2
-rw-r--r--tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr2
-rw-r--r--tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr2
-rw-r--r--tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr2
-rw-r--r--tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr2
-rw-r--r--tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr4
-rw-r--r--tests/ui/parser/dyn-trait-compatibility.rs2
-rw-r--r--tests/ui/parser/dyn-trait-compatibility.stderr16
-rw-r--r--tests/ui/parser/issues/issue-110014.rs3
-rw-r--r--tests/ui/parser/issues/issue-110014.stderr19
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/struct.stderr9
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/variant.stderr20
-rw-r--r--tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed6
-rw-r--r--tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs6
-rw-r--r--tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr13
-rw-r--r--tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs2
-rw-r--r--tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr14
-rw-r--r--tests/ui/ufcs/ufcs-partially-resolved.rs44
-rw-r--r--tests/ui/ufcs/ufcs-partially-resolved.stderr190
-rw-r--r--triagebot.toml5
445 files changed, 4275 insertions, 4982 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 07dcca0fd47..d4fca32d750 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -632,7 +632,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "syn 1.0.102",
- "synstructure",
+ "synstructure 0.12.6",
 ]
 
 [[package]]
@@ -4994,8 +4994,8 @@ dependencies = [
  "fluent-syntax",
  "proc-macro2",
  "quote",
- "syn 1.0.102",
- "synstructure",
+ "syn 2.0.8",
+ "synstructure 0.13.0",
  "unic-langid",
 ]
 
@@ -6132,6 +6132,18 @@ dependencies = [
 ]
 
 [[package]]
+name = "synstructure"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.8",
+ "unicode-xid",
+]
+
+[[package]]
 name = "tar"
 version = "0.4.38"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -7154,7 +7166,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "syn 1.0.102",
- "synstructure",
+ "synstructure 0.12.6",
 ]
 
 [[package]]
@@ -7175,7 +7187,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "syn 1.0.102",
- "synstructure",
+ "synstructure 0.12.6",
 ]
 
 [[package]]
@@ -7204,5 +7216,5 @@ dependencies = [
  "proc-macro2",
  "quote",
  "syn 1.0.102",
- "synstructure",
+ "synstructure 0.12.6",
 ]
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
index 68205fa4558..84f75caa692 100644
--- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs
@@ -181,8 +181,8 @@ trait TypeOpInfo<'tcx> {
         };
 
         let placeholder_region = tcx.mk_re_placeholder(ty::Placeholder {
-            name: placeholder.name,
             universe: adjusted_universe.into(),
+            bound: placeholder.bound,
         });
 
         let error_region =
@@ -191,8 +191,8 @@ trait TypeOpInfo<'tcx> {
                     error_placeholder.universe.as_u32().checked_sub(base_universe.as_u32());
                 adjusted_universe.map(|adjusted| {
                     tcx.mk_re_placeholder(ty::Placeholder {
-                        name: error_placeholder.name,
                         universe: adjusted.into(),
+                        bound: error_placeholder.bound,
                     })
                 })
             } else {
diff --git a/compiler/rustc_borrowck/src/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs
index fd1fda2ee4b..e2d04324f3b 100644
--- a/compiler/rustc_borrowck/src/diagnostics/find_use.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs
@@ -11,7 +11,7 @@ use crate::{
 };
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_middle::mir::visit::{MirVisitable, PlaceContext, Visitor};
-use rustc_middle::mir::{Body, Local, Location};
+use rustc_middle::mir::{self, Body, Local, Location};
 use rustc_middle::ty::{RegionVid, TyCtxt};
 
 pub(crate) fn find<'tcx>(
@@ -70,7 +70,10 @@ impl<'cx, 'tcx> UseFinder<'cx, 'tcx> {
                             block_data
                                 .terminator()
                                 .successors()
-                                .filter(|&bb| Some(&Some(bb)) != block_data.terminator().unwind())
+                                .filter(|&bb| {
+                                    Some(&mir::UnwindAction::Cleanup(bb))
+                                        != block_data.terminator().unwind()
+                                })
                                 .map(|bb| Location { statement_index: 0, block: bb }),
                         );
                     }
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 7bd4331c5ed..110354a20d8 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -467,9 +467,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         if let ty::Ref(region, ..) = ty.kind() {
             match **region {
                 ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
-                | ty::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
-                    printer.region_highlight_mode.highlighting_bound_region(br, counter)
-                }
+                | ty::RePlaceholder(ty::PlaceholderRegion {
+                    bound: ty::BoundRegion { kind: br, .. },
+                    ..
+                }) => printer.region_highlight_mode.highlighting_bound_region(br, counter),
                 _ => {}
             }
         }
@@ -485,9 +486,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         let region = if let ty::Ref(region, ..) = ty.kind() {
             match **region {
                 ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
-                | ty::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
-                    printer.region_highlight_mode.highlighting_bound_region(br, counter)
-                }
+                | ty::RePlaceholder(ty::PlaceholderRegion {
+                    bound: ty::BoundRegion { kind: br, .. },
+                    ..
+                }) => printer.region_highlight_mode.highlighting_bound_region(br, counter),
                 _ => {}
             }
             region
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index ffe82b46cfd..9fcebeb0acd 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -207,7 +207,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             .regioncx
             .placeholders_contained_in(lower_bound)
             .map(|placeholder| {
-                if let Some(id) = placeholder.name.get_id()
+                if let Some(id) = placeholder.bound.kind.get_id()
                     && let Some(placeholder_id) = id.as_local()
                     && let gat_hir_id = hir.local_def_id_to_hir_id(placeholder_id)
                     && let Some(generics_impl) = hir.get_parent(gat_hir_id).generics()
diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs
index a71c4163286..498d254da65 100644
--- a/compiler/rustc_borrowck/src/invalidation.rs
+++ b/compiler/rustc_borrowck/src/invalidation.rs
@@ -125,7 +125,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
                 args,
                 destination,
                 target: _,
-                cleanup: _,
+                unwind: _,
                 from_hir_call: _,
                 fn_span: _,
             } => {
@@ -135,7 +135,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
                 }
                 self.mutate_place(location, *destination, Deep);
             }
-            TerminatorKind::Assert { cond, expected: _, msg, target: _, cleanup: _ } => {
+            TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => {
                 self.consume_operand(location, cond);
                 use rustc_middle::mir::AssertKind;
                 if let AssertKind::BoundsCheck { len, index } = msg {
@@ -173,7 +173,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
                 options: _,
                 line_spans: _,
                 destination: _,
-                cleanup: _,
+                unwind: _,
             } => {
                 for op in operands {
                     match op {
@@ -198,7 +198,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
                 }
             }
             TerminatorKind::Goto { target: _ }
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Unreachable
             | TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ }
             | TerminatorKind::FalseUnwind { real_target: _, unwind: _ } => {
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 1d4d1406239..3d876155fc9 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -740,7 +740,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
                 args,
                 destination,
                 target: _,
-                cleanup: _,
+                unwind: _,
                 from_hir_call: _,
                 fn_span: _,
             } => {
@@ -750,7 +750,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
                 }
                 self.mutate_place(loc, (*destination, span), Deep, flow_state);
             }
-            TerminatorKind::Assert { cond, expected: _, msg, target: _, cleanup: _ } => {
+            TerminatorKind::Assert { cond, expected: _, msg, target: _, unwind: _ } => {
                 self.consume_operand(loc, (cond, span), flow_state);
                 use rustc_middle::mir::AssertKind;
                 if let AssertKind::BoundsCheck { len, index } = msg {
@@ -770,7 +770,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
                 options: _,
                 line_spans: _,
                 destination: _,
-                cleanup: _,
+                unwind: _,
             } => {
                 for op in operands {
                     match op {
@@ -801,7 +801,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
             }
 
             TerminatorKind::Goto { target: _ }
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Unreachable
             | TerminatorKind::Resume
             | TerminatorKind::Return
@@ -845,7 +845,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
                 }
             }
 
-            TerminatorKind::Abort
+            TerminatorKind::Terminate
             | TerminatorKind::Assert { .. }
             | TerminatorKind::Call { .. }
             | TerminatorKind::Drop { .. }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 2fc4e32ecb2..624a4a00c31 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1300,7 +1300,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         match &term.kind {
             TerminatorKind::Goto { .. }
             | TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Unreachable
@@ -1342,9 +1342,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
                     let region_ctxt_fn = || {
                         let reg_info = match br.kind {
-                            ty::BoundRegionKind::BrAnon(_, Some(span)) => {
-                                BoundRegionInfo::Span(span)
-                            }
+                            ty::BoundRegionKind::BrAnon(Some(span)) => BoundRegionInfo::Span(span),
                             ty::BoundRegionKind::BrAnon(..) => {
                                 BoundRegionInfo::Name(Symbol::intern("anon"))
                             }
@@ -1584,7 +1582,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     span_mirbug!(self, block_data, "resume on non-cleanup block!")
                 }
             }
-            TerminatorKind::Abort => {
+            TerminatorKind::Terminate => {
                 if !is_cleanup {
                     span_mirbug!(self, block_data, "abort on non-cleanup block!")
                 }
@@ -1610,25 +1608,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             }
             TerminatorKind::Unreachable => {}
             TerminatorKind::Drop { target, unwind, .. }
-            | TerminatorKind::Assert { target, cleanup: unwind, .. } => {
+            | TerminatorKind::Assert { target, unwind, .. } => {
                 self.assert_iscleanup(body, block_data, target, is_cleanup);
-                if let Some(unwind) = unwind {
-                    if is_cleanup {
-                        span_mirbug!(self, block_data, "unwind on cleanup block")
-                    }
-                    self.assert_iscleanup(body, block_data, unwind, true);
-                }
+                self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
             }
-            TerminatorKind::Call { ref target, cleanup, .. } => {
+            TerminatorKind::Call { ref target, unwind, .. } => {
                 if let &Some(target) = target {
                     self.assert_iscleanup(body, block_data, target, is_cleanup);
                 }
-                if let Some(cleanup) = cleanup {
-                    if is_cleanup {
-                        span_mirbug!(self, block_data, "cleanup on cleanup block")
-                    }
-                    self.assert_iscleanup(body, block_data, cleanup, true);
-                }
+                self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
             }
             TerminatorKind::FalseEdge { real_target, imaginary_target } => {
                 self.assert_iscleanup(body, block_data, real_target, is_cleanup);
@@ -1636,23 +1624,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             }
             TerminatorKind::FalseUnwind { real_target, unwind } => {
                 self.assert_iscleanup(body, block_data, real_target, is_cleanup);
-                if let Some(unwind) = unwind {
-                    if is_cleanup {
-                        span_mirbug!(self, block_data, "cleanup in cleanup block via false unwind");
-                    }
-                    self.assert_iscleanup(body, block_data, unwind, true);
-                }
+                self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
             }
-            TerminatorKind::InlineAsm { destination, cleanup, .. } => {
+            TerminatorKind::InlineAsm { destination, unwind, .. } => {
                 if let Some(target) = destination {
                     self.assert_iscleanup(body, block_data, target, is_cleanup);
                 }
-                if let Some(cleanup) = cleanup {
-                    if is_cleanup {
-                        span_mirbug!(self, block_data, "cleanup on cleanup block")
-                    }
-                    self.assert_iscleanup(body, block_data, cleanup, true);
-                }
+                self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
             }
         }
     }
@@ -1669,6 +1647,29 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         }
     }
 
+    fn assert_iscleanup_unwind(
+        &mut self,
+        body: &Body<'tcx>,
+        ctxt: &dyn fmt::Debug,
+        unwind: UnwindAction,
+        is_cleanup: bool,
+    ) {
+        match unwind {
+            UnwindAction::Cleanup(unwind) => {
+                if is_cleanup {
+                    span_mirbug!(self, ctxt, "unwind on cleanup block")
+                }
+                self.assert_iscleanup(body, ctxt, unwind, true);
+            }
+            UnwindAction::Continue => {
+                if is_cleanup {
+                    span_mirbug!(self, ctxt, "unwind on cleanup block")
+                }
+            }
+            UnwindAction::Unreachable | UnwindAction::Terminate => (),
+        }
+    }
+
     fn check_local(&mut self, body: &Body<'tcx>, local: Local, local_decl: &LocalDecl<'tcx>) {
         match body.local_kind(local) {
             LocalKind::ReturnPointer | LocalKind::Arg => {
diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
index 305e2c8fe8e..83429f2ddef 100644
--- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs
+++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs
@@ -123,8 +123,8 @@ impl<'tcx> TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx>
             .constraints
             .placeholder_region(self.type_checker.infcx, placeholder);
 
-        let reg_info = match placeholder.name {
-            ty::BoundRegionKind::BrAnon(_, Some(span)) => BoundRegionInfo::Span(span),
+        let reg_info = match placeholder.bound.kind {
+            ty::BoundRegionKind::BrAnon(Some(span)) => BoundRegionInfo::Span(span),
             ty::BoundRegionKind::BrAnon(..) => BoundRegionInfo::Name(Symbol::intern("anon")),
             ty::BoundRegionKind::BrNamed(_, name) => BoundRegionInfo::Name(name),
             ty::BoundRegionKind::BrEnv => BoundRegionInfo::Name(Symbol::intern("env")),
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index 71177b8789b..7697b592e33 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -7,7 +7,6 @@
 #![feature(box_patterns)]
 #![feature(decl_macro)]
 #![feature(if_let_guard)]
-#![feature(is_some_and)]
 #![feature(is_sorted)]
 #![feature(let_chains)]
 #![feature(proc_macro_internals)]
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 2630f02e6eb..f5301f9f7f1 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -345,7 +345,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
             TerminatorKind::Return => {
                 crate::abi::codegen_return(fx);
             }
-            TerminatorKind::Assert { cond, expected, msg, target, cleanup: _ } => {
+            TerminatorKind::Assert { cond, expected, msg, target, unwind: _ } => {
                 if !fx.tcx.sess.overflow_checks() && msg.is_optional_overflow_check() {
                     let target = fx.get_block(*target);
                     fx.bcx.ins().jump(target, &[]);
@@ -450,7 +450,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
                 destination,
                 target,
                 fn_span,
-                cleanup: _,
+                unwind: _,
                 from_hir_call: _,
             } => {
                 fx.tcx.prof.generic_activity("codegen call").run(|| {
@@ -470,7 +470,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
                 options,
                 destination,
                 line_spans: _,
-                cleanup: _,
+                unwind: _,
             } => {
                 if options.contains(InlineAsmOptions::MAY_UNWIND) {
                     fx.tcx.sess.span_fatal(
@@ -488,7 +488,7 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
                     *destination,
                 );
             }
-            TerminatorKind::Abort => {
+            TerminatorKind::Terminate => {
                 codegen_panic_cannot_unwind(fx, source_info);
             }
             TerminatorKind::Resume => {
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index ebb4de33f99..e87f4e25891 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -549,7 +549,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
                     TerminatorKind::Goto { .. }
                     | TerminatorKind::SwitchInt { .. }
                     | TerminatorKind::Resume
-                    | TerminatorKind::Abort
+                    | TerminatorKind::Terminate
                     | TerminatorKind::Return
                     | TerminatorKind::Unreachable
                     | TerminatorKind::Drop { .. }
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index d9f8170a3cf..e7668341eb6 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -381,7 +381,7 @@ impl<'tcx> AsmMethods<'tcx> for CodegenCx<'_, 'tcx> {
         }
 
         unsafe {
-            llvm::LLVMRustAppendModuleInlineAsm(
+            llvm::LLVMAppendModuleInlineAsm(
                 self.llmod,
                 template_str.as_ptr().cast(),
                 template_str.len(),
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index fb563f70ed0..7136f750f39 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -904,9 +904,9 @@ unsafe fn embed_bitcode(
         // We need custom section flags, so emit module-level inline assembly.
         let section_flags = if cgcx.is_pe_coff { "n" } else { "e" };
         let asm = create_section_with_flags_asm(".llvmbc", section_flags, bitcode);
-        llvm::LLVMRustAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len());
+        llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len());
         let asm = create_section_with_flags_asm(".llvmcmd", section_flags, cmdline.as_bytes());
-        llvm::LLVMRustAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len());
+        llvm::LLVMAppendModuleInlineAsm(llmod, asm.as_ptr().cast(), asm.len());
     }
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 63e8a67db53..6819a2af09d 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -2,7 +2,7 @@ use crate::abi::FnAbiLlvmExt;
 use crate::attributes;
 use crate::common::Funclet;
 use crate::context::CodegenCx;
-use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock};
+use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, True};
 use crate::type_::Type;
 use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
@@ -841,7 +841,15 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
     }
 
     fn intcast(&mut self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value {
-        unsafe { llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty, is_signed) }
+        unsafe {
+            llvm::LLVMBuildIntCast2(
+                self.llbuilder,
+                val,
+                dest_ty,
+                if is_signed { True } else { False },
+                UNNAMED,
+            )
+        }
     }
 
     fn pointercast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
@@ -1001,11 +1009,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
     fn cleanup_pad(&mut self, parent: Option<&'ll Value>, args: &[&'ll Value]) -> Funclet<'ll> {
         let name = cstr!("cleanuppad");
         let ret = unsafe {
-            llvm::LLVMRustBuildCleanupPad(
+            llvm::LLVMBuildCleanupPad(
                 self.llbuilder,
                 parent,
-                args.len() as c_uint,
                 args.as_ptr(),
+                args.len() as c_uint,
                 name.as_ptr(),
             )
         };
@@ -1014,7 +1022,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
 
     fn cleanup_ret(&mut self, funclet: &Funclet<'ll>, unwind: Option<&'ll BasicBlock>) {
         unsafe {
-            llvm::LLVMRustBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind)
+            llvm::LLVMBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind)
                 .expect("LLVM does not have support for cleanupret");
         }
     }
@@ -1022,11 +1030,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
     fn catch_pad(&mut self, parent: &'ll Value, args: &[&'ll Value]) -> Funclet<'ll> {
         let name = cstr!("catchpad");
         let ret = unsafe {
-            llvm::LLVMRustBuildCatchPad(
+            llvm::LLVMBuildCatchPad(
                 self.llbuilder,
                 parent,
-                args.len() as c_uint,
                 args.as_ptr(),
+                args.len() as c_uint,
                 name.as_ptr(),
             )
         };
@@ -1041,7 +1049,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
     ) -> &'ll Value {
         let name = cstr!("catchswitch");
         let ret = unsafe {
-            llvm::LLVMRustBuildCatchSwitch(
+            llvm::LLVMBuildCatchSwitch(
                 self.llbuilder,
                 parent,
                 unwind,
@@ -1052,7 +1060,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         let ret = ret.expect("LLVM does not have support for catchswitch");
         for handler in handlers {
             unsafe {
-                llvm::LLVMRustAddHandler(ret, handler);
+                llvm::LLVMAddHandler(ret, handler);
             }
         }
         ret
@@ -1376,8 +1384,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
     }
 
     pub fn catch_ret(&mut self, funclet: &Funclet<'ll>, unwind: &'ll BasicBlock) -> &'ll Value {
-        let ret =
-            unsafe { llvm::LLVMRustBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind) };
+        let ret = unsafe { llvm::LLVMBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind) };
         ret.expect("LLVM does not have support for catchret")
     }
 
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index 9116e71beac..940358acde9 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -7,7 +7,6 @@ use crate::type_::Type;
 use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
 use cstr::cstr;
-use libc::c_uint;
 use rustc_codegen_ssa::traits::*;
 use rustc_hir::def_id::DefId;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
@@ -486,10 +485,10 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
             // go into custom sections of the wasm executable.
             if self.tcx.sess.target.is_like_wasm {
                 if let Some(section) = attrs.link_section {
-                    let section = llvm::LLVMMDStringInContext(
+                    let section = llvm::LLVMMDStringInContext2(
                         self.llcx,
                         section.as_str().as_ptr().cast(),
-                        section.as_str().len() as c_uint,
+                        section.as_str().len(),
                     );
                     assert!(alloc.provenance().ptrs().is_empty());
 
@@ -498,17 +497,15 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
                     // as part of the interpreter execution).
                     let bytes =
                         alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len());
-                    let alloc = llvm::LLVMMDStringInContext(
-                        self.llcx,
-                        bytes.as_ptr().cast(),
-                        bytes.len() as c_uint,
-                    );
+                    let alloc =
+                        llvm::LLVMMDStringInContext2(self.llcx, bytes.as_ptr().cast(), bytes.len());
                     let data = [section, alloc];
-                    let meta = llvm::LLVMMDNodeInContext(self.llcx, data.as_ptr(), 2);
+                    let meta = llvm::LLVMMDNodeInContext2(self.llcx, data.as_ptr(), data.len());
+                    let val = llvm::LLVMMetadataAsValue(self.llcx, meta);
                     llvm::LLVMAddNamedMetadataOperand(
                         self.llmod,
                         "wasm.custom_sections\0".as_ptr().cast(),
-                        meta,
+                        val,
                     );
                 }
             } else {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index 4bf6762d1f6..21a0a60b012 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -864,8 +864,6 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>(
         );
 
         if tcx.sess.opts.unstable_opts.profile {
-            let cu_desc_metadata =
-                llvm::LLVMRustMetadataAsValue(debug_context.llcontext, unit_metadata);
             let default_gcda_path = &output_filenames.with_extension("gcda");
             let gcda_path =
                 tcx.sess.opts.unstable_opts.profile_emit.as_ref().unwrap_or(default_gcda_path);
@@ -873,20 +871,17 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>(
             let gcov_cu_info = [
                 path_to_mdstring(debug_context.llcontext, &output_filenames.with_extension("gcno")),
                 path_to_mdstring(debug_context.llcontext, gcda_path),
-                cu_desc_metadata,
+                unit_metadata,
             ];
-            let gcov_metadata = llvm::LLVMMDNodeInContext(
+            let gcov_metadata = llvm::LLVMMDNodeInContext2(
                 debug_context.llcontext,
                 gcov_cu_info.as_ptr(),
-                gcov_cu_info.len() as c_uint,
+                gcov_cu_info.len(),
             );
+            let val = llvm::LLVMMetadataAsValue(debug_context.llcontext, gcov_metadata);
 
             let llvm_gcov_ident = cstr!("llvm.gcov");
-            llvm::LLVMAddNamedMetadataOperand(
-                debug_context.llmod,
-                llvm_gcov_ident.as_ptr(),
-                gcov_metadata,
-            );
+            llvm::LLVMAddNamedMetadataOperand(debug_context.llmod, llvm_gcov_ident.as_ptr(), val);
         }
 
         // Insert `llvm.ident` metadata on the wasm targets since that will
@@ -907,15 +902,9 @@ pub fn build_compile_unit_di_node<'ll, 'tcx>(
         return unit_metadata;
     };
 
-    fn path_to_mdstring<'ll>(llcx: &'ll llvm::Context, path: &Path) -> &'ll Value {
+    fn path_to_mdstring<'ll>(llcx: &'ll llvm::Context, path: &Path) -> &'ll llvm::Metadata {
         let path_str = path_to_c_string(path);
-        unsafe {
-            llvm::LLVMMDStringInContext(
-                llcx,
-                path_str.as_ptr(),
-                path_str.as_bytes().len() as c_uint,
-            )
-        }
+        unsafe { llvm::LLVMMDStringInContext2(llcx, path_str.as_ptr(), path_str.as_bytes().len()) }
     }
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index 41a75c9d775..d56c414cf65 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -209,8 +209,7 @@ impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> {
 
     fn set_dbg_loc(&mut self, dbg_loc: &'ll DILocation) {
         unsafe {
-            let dbg_loc_as_llval = llvm::LLVMRustMetadataAsValue(self.cx().llcx, dbg_loc);
-            llvm::LLVMSetCurrentDebugLocation(self.llbuilder, dbg_loc_as_llval);
+            llvm::LLVMSetCurrentDebugLocation2(self.llbuilder, dbg_loc);
         }
     }
 
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 556c6602ff4..09f3fe02165 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1018,7 +1018,7 @@ extern "C" {
     pub fn LLVMSetDataLayout(M: &Module, Triple: *const c_char);
 
     /// See Module::setModuleInlineAsm.
-    pub fn LLVMRustAppendModuleInlineAsm(M: &Module, Asm: *const c_char, AsmLen: size_t);
+    pub fn LLVMAppendModuleInlineAsm(M: &Module, Asm: *const c_char, Len: size_t);
 
     /// See llvm::LLVMTypeKind::getTypeID.
     pub fn LLVMRustGetTypeKind(Ty: &Type) -> TypeKind;
@@ -1065,7 +1065,7 @@ extern "C" {
 
     // Operations on other types
     pub fn LLVMVoidTypeInContext(C: &Context) -> &Type;
-    pub fn LLVMRustMetadataTypeInContext(C: &Context) -> &Type;
+    pub fn LLVMMetadataTypeInContext(C: &Context) -> &Type;
 
     // Operations on all values
     pub fn LLVMTypeOf(Val: &Value) -> &Type;
@@ -1084,7 +1084,12 @@ extern "C" {
     pub fn LLVMGetPoison(Ty: &Type) -> &Value;
 
     // Operations on metadata
+    // FIXME: deprecated, replace with LLVMMDStringInContext2
     pub fn LLVMMDStringInContext(C: &Context, Str: *const c_char, SLen: c_uint) -> &Value;
+
+    pub fn LLVMMDStringInContext2(C: &Context, Str: *const c_char, SLen: size_t) -> &Metadata;
+
+    // FIXME: deprecated, replace with LLVMMDNodeInContext2
     pub fn LLVMMDNodeInContext<'a>(
         C: &'a Context,
         Vals: *const &'a Value,
@@ -1123,6 +1128,8 @@ extern "C" {
         Packed: Bool,
     ) -> &'a Value;
 
+    // FIXME: replace with LLVMConstArray2 when bumped minimal version to llvm-17
+    // https://github.com/llvm/llvm-project/commit/35276f16e5a2cae0dfb49c0fbf874d4d2f177acc
     pub fn LLVMConstArray<'a>(
         ElementTy: &'a Type,
         ConstantVals: *const &'a Value,
@@ -1262,7 +1269,7 @@ extern "C" {
     pub fn LLVMDisposeBuilder<'a>(Builder: &'a mut Builder<'a>);
 
     // Metadata
-    pub fn LLVMSetCurrentDebugLocation<'a>(Builder: &Builder<'a>, L: &'a Value);
+    pub fn LLVMSetCurrentDebugLocation2<'a>(Builder: &Builder<'a>, Loc: &'a Metadata);
 
     // Terminators
     pub fn LLVMBuildRetVoid<'a>(B: &Builder<'a>) -> &'a Value;
@@ -1302,38 +1309,38 @@ extern "C" {
     pub fn LLVMBuildResume<'a>(B: &Builder<'a>, Exn: &'a Value) -> &'a Value;
     pub fn LLVMBuildUnreachable<'a>(B: &Builder<'a>) -> &'a Value;
 
-    pub fn LLVMRustBuildCleanupPad<'a>(
+    pub fn LLVMBuildCleanupPad<'a>(
         B: &Builder<'a>,
         ParentPad: Option<&'a Value>,
-        ArgCnt: c_uint,
         Args: *const &'a Value,
+        NumArgs: c_uint,
         Name: *const c_char,
     ) -> Option<&'a Value>;
-    pub fn LLVMRustBuildCleanupRet<'a>(
+    pub fn LLVMBuildCleanupRet<'a>(
         B: &Builder<'a>,
         CleanupPad: &'a Value,
-        UnwindBB: Option<&'a BasicBlock>,
+        BB: Option<&'a BasicBlock>,
     ) -> Option<&'a Value>;
-    pub fn LLVMRustBuildCatchPad<'a>(
+    pub fn LLVMBuildCatchPad<'a>(
         B: &Builder<'a>,
         ParentPad: &'a Value,
-        ArgCnt: c_uint,
         Args: *const &'a Value,
+        NumArgs: c_uint,
         Name: *const c_char,
     ) -> Option<&'a Value>;
-    pub fn LLVMRustBuildCatchRet<'a>(
+    pub fn LLVMBuildCatchRet<'a>(
         B: &Builder<'a>,
-        Pad: &'a Value,
+        CatchPad: &'a Value,
         BB: &'a BasicBlock,
     ) -> Option<&'a Value>;
-    pub fn LLVMRustBuildCatchSwitch<'a>(
+    pub fn LLVMBuildCatchSwitch<'a>(
         Builder: &Builder<'a>,
         ParentPad: Option<&'a Value>,
-        BB: Option<&'a BasicBlock>,
+        UnwindBB: Option<&'a BasicBlock>,
         NumHandlers: c_uint,
         Name: *const c_char,
     ) -> Option<&'a Value>;
-    pub fn LLVMRustAddHandler<'a>(CatchSwitch: &'a Value, Handler: &'a BasicBlock);
+    pub fn LLVMAddHandler<'a>(CatchSwitch: &'a Value, Dest: &'a BasicBlock);
     pub fn LLVMSetPersonalityFn<'a>(Func: &'a Value, Pers: &'a Value);
 
     // Add a case to the switch instruction
@@ -1627,11 +1634,12 @@ extern "C" {
         DestTy: &'a Type,
         Name: *const c_char,
     ) -> &'a Value;
-    pub fn LLVMRustBuildIntCast<'a>(
+    pub fn LLVMBuildIntCast2<'a>(
         B: &Builder<'a>,
         Val: &'a Value,
         DestTy: &'a Type,
-        IsSigned: bool,
+        IsSigned: Bool,
+        Name: *const c_char,
     ) -> &'a Value;
 
     // Comparisons
@@ -1920,7 +1928,7 @@ extern "C" {
     );
     pub fn LLVMRustHasModuleFlag(M: &Module, name: *const c_char, len: size_t) -> bool;
 
-    pub fn LLVMRustMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value;
+    pub fn LLVMMetadataAsValue<'a>(C: &'a Context, MD: &'a Metadata) -> &'a Value;
 
     pub fn LLVMRustDIBuilderCreate(M: &Module) -> &mut DIBuilder<'_>;
 
diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs
index ff111d96f84..bef4647f207 100644
--- a/compiler/rustc_codegen_llvm/src/type_.rs
+++ b/compiler/rustc_codegen_llvm/src/type_.rs
@@ -53,7 +53,7 @@ impl<'ll> CodegenCx<'ll, '_> {
     }
 
     pub(crate) fn type_metadata(&self) -> &'ll Type {
-        unsafe { llvm::LLVMRustMetadataTypeInContext(self.llcx) }
+        unsafe { llvm::LLVMMetadataTypeInContext(self.llcx) }
     }
 
     ///x Creates an integer type with the given number of bits, e.g., i24
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 4ab56699922..3e3fcc08bd6 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -13,8 +13,7 @@ use object::{
 use snap::write::FrameEncoder;
 
 use rustc_data_structures::memmap::Mmap;
-use rustc_data_structures::owning_ref::OwningRef;
-use rustc_data_structures::rustc_erase_owner;
+use rustc_data_structures::owned_slice::try_slice_owned;
 use rustc_data_structures::sync::MetadataRef;
 use rustc_metadata::fs::METADATA_FILENAME;
 use rustc_metadata::EncodedMetadata;
@@ -42,10 +41,10 @@ fn load_metadata_with(
 ) -> Result<MetadataRef, String> {
     let file =
         File::open(path).map_err(|e| format!("failed to open file '{}': {}", path.display(), e))?;
-    let data = unsafe { Mmap::map(file) }
-        .map_err(|e| format!("failed to mmap file '{}': {}", path.display(), e))?;
-    let metadata = OwningRef::new(data).try_map(f)?;
-    return Ok(rustc_erase_owner!(metadata.map_owner_box()));
+
+    unsafe { Mmap::map(file) }
+        .map_err(|e| format!("failed to mmap file '{}': {}", path.display(), e))
+        .and_then(|mmap| try_slice_owned(mmap, |mmap| f(mmap)))
 }
 
 impl MetadataLoader for DefaultMetadataLoader {
diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
index dcf533dc39c..115a41050d2 100644
--- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
@@ -284,7 +284,7 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKi
             match data.terminator().kind {
                 TerminatorKind::Goto { .. }
                 | TerminatorKind::Resume
-                | TerminatorKind::Abort
+                | TerminatorKind::Terminate
                 | TerminatorKind::Return
                 | TerminatorKind::GeneratorDrop
                 | TerminatorKind::Unreachable
@@ -292,11 +292,11 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKi
                 | TerminatorKind::Yield { .. }
                 | TerminatorKind::FalseEdge { .. }
                 | TerminatorKind::FalseUnwind { .. } => { /* nothing to do */ }
-                TerminatorKind::Call { cleanup: unwind, .. }
-                | TerminatorKind::InlineAsm { cleanup: unwind, .. }
-                | TerminatorKind::Assert { cleanup: unwind, .. }
+                TerminatorKind::Call { unwind, .. }
+                | TerminatorKind::InlineAsm { unwind, .. }
+                | TerminatorKind::Assert { unwind, .. }
                 | TerminatorKind::Drop { unwind, .. } => {
-                    if let Some(unwind) = unwind {
+                    if let mir::UnwindAction::Cleanup(unwind) = unwind {
                         debug!(
                             "cleanup_kinds: {:?}/{:?} registering {:?} as funclet",
                             bb, data, unwind
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index c086d1b7f5a..dd86977817f 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -147,7 +147,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
     }
 
     /// Call `fn_ptr` of `fn_abi` with the arguments `llargs`, the optional
-    /// return destination `destination` and the cleanup function `cleanup`.
+    /// return destination `destination` and the unwind action `unwind`.
     fn do_call<Bx: BuilderMethods<'a, 'tcx>>(
         &self,
         fx: &mut FunctionCx<'a, 'tcx, Bx>,
@@ -156,7 +156,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
         fn_ptr: Bx::Value,
         llargs: &[Bx::Value],
         destination: Option<(ReturnDest<'tcx, Bx::Value>, mir::BasicBlock)>,
-        cleanup: Option<mir::BasicBlock>,
+        mut unwind: mir::UnwindAction,
         copied_constant_arguments: &[PlaceRef<'tcx, <Bx as BackendTypes>::Value>],
         mergeable_succ: bool,
     ) -> MergingSucc {
@@ -164,23 +164,23 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
         // do an invoke, otherwise do a call.
         let fn_ty = bx.fn_decl_backend_type(&fn_abi);
 
-        let unwind_block = if let Some(cleanup) = cleanup.filter(|_| fn_abi.can_unwind) {
-            Some(self.llbb_with_cleanup(fx, cleanup))
-        } else if fx.mir[self.bb].is_cleanup
-            && fn_abi.can_unwind
-            && !base::wants_msvc_seh(fx.cx.tcx().sess)
-        {
-            // Exception must not propagate out of the execution of a cleanup (doing so
-            // can cause undefined behaviour). We insert a double unwind guard for
-            // functions that can potentially unwind to protect against this.
-            //
-            // This is not necessary for SEH which does not use successive unwinding
-            // like Itanium EH. EH frames in SEH are different from normal function
-            // frames and SEH will abort automatically if an exception tries to
-            // propagate out from cleanup.
-            Some(fx.double_unwind_guard())
-        } else {
-            None
+        if !fn_abi.can_unwind {
+            unwind = mir::UnwindAction::Unreachable;
+        }
+
+        let unwind_block = match unwind {
+            mir::UnwindAction::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)),
+            mir::UnwindAction::Continue => None,
+            mir::UnwindAction::Unreachable => None,
+            mir::UnwindAction::Terminate => {
+                if fx.mir[self.bb].is_cleanup && base::wants_msvc_seh(fx.cx.tcx().sess) {
+                    // SEH will abort automatically if an exception tries to
+                    // propagate out from cleanup.
+                    None
+                } else {
+                    Some(fx.terminate_block())
+                }
+            }
         };
 
         if let Some(unwind_block) = unwind_block {
@@ -234,7 +234,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
         }
     }
 
-    /// Generates inline assembly with optional `destination` and `cleanup`.
+    /// Generates inline assembly with optional `destination` and `unwind`.
     fn do_inlineasm<Bx: BuilderMethods<'a, 'tcx>>(
         &self,
         fx: &mut FunctionCx<'a, 'tcx, Bx>,
@@ -244,11 +244,18 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
         options: InlineAsmOptions,
         line_spans: &[Span],
         destination: Option<mir::BasicBlock>,
-        cleanup: Option<mir::BasicBlock>,
+        unwind: mir::UnwindAction,
         instance: Instance<'_>,
         mergeable_succ: bool,
     ) -> MergingSucc {
-        if let Some(cleanup) = cleanup {
+        let unwind_target = match unwind {
+            mir::UnwindAction::Cleanup(cleanup) => Some(self.llbb_with_cleanup(fx, cleanup)),
+            mir::UnwindAction::Terminate => Some(fx.terminate_block()),
+            mir::UnwindAction::Continue => None,
+            mir::UnwindAction::Unreachable => None,
+        };
+
+        if let Some(cleanup) = unwind_target {
             let ret_llbb = if let Some(target) = destination {
                 fx.llbb(target)
             } else {
@@ -261,7 +268,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
                 options,
                 line_spans,
                 instance,
-                Some((ret_llbb, self.llbb_with_cleanup(fx, cleanup), self.funclet(fx))),
+                Some((ret_llbb, cleanup, self.funclet(fx))),
             );
             MergingSucc::False
         } else {
@@ -431,7 +438,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         bx: &mut Bx,
         location: mir::Place<'tcx>,
         target: mir::BasicBlock,
-        unwind: Option<mir::BasicBlock>,
+        unwind: mir::UnwindAction,
         mergeable_succ: bool,
     ) -> MergingSucc {
         let ty = location.ty(self.mir, bx.tcx()).ty;
@@ -552,7 +559,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         expected: bool,
         msg: &mir::AssertMessage<'tcx>,
         target: mir::BasicBlock,
-        cleanup: Option<mir::BasicBlock>,
+        unwind: mir::UnwindAction,
         mergeable_succ: bool,
     ) -> MergingSucc {
         let span = terminator.source_info.span;
@@ -618,12 +625,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let (fn_abi, llfn) = common::build_langcall(bx, Some(span), lang_item);
 
         // Codegen the actual panic invoke/call.
-        let merging_succ = helper.do_call(self, bx, fn_abi, llfn, &args, None, cleanup, &[], false);
+        let merging_succ = helper.do_call(self, bx, fn_abi, llfn, &args, None, unwind, &[], false);
         assert_eq!(merging_succ, MergingSucc::False);
         MergingSucc::False
     }
 
-    fn codegen_abort_terminator(
+    fn codegen_terminate_terminator(
         &mut self,
         helper: TerminatorCodegenHelper<'tcx>,
         bx: &mut Bx,
@@ -636,7 +643,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let (fn_abi, llfn) = common::build_langcall(bx, Some(span), LangItem::PanicCannotUnwind);
 
         // Codegen the actual panic invoke/call.
-        let merging_succ = helper.do_call(self, bx, fn_abi, llfn, &[], None, None, &[], false);
+        let merging_succ = helper.do_call(
+            self,
+            bx,
+            fn_abi,
+            llfn,
+            &[],
+            None,
+            mir::UnwindAction::Unreachable,
+            &[],
+            false,
+        );
         assert_eq!(merging_succ, MergingSucc::False);
     }
 
@@ -649,7 +666,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         instance: Option<Instance<'tcx>>,
         source_info: mir::SourceInfo,
         target: Option<mir::BasicBlock>,
-        cleanup: Option<mir::BasicBlock>,
+        unwind: mir::UnwindAction,
         mergeable_succ: bool,
     ) -> Option<MergingSucc> {
         // Emit a panic or a no-op for `assert_*` intrinsics.
@@ -696,7 +713,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     llfn,
                     &[msg.0, msg.1],
                     target.as_ref().map(|bb| (ReturnDest::Nothing, *bb)),
-                    cleanup,
+                    unwind,
                     &[],
                     mergeable_succ,
                 )
@@ -719,7 +736,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         args: &[mir::Operand<'tcx>],
         destination: mir::Place<'tcx>,
         target: Option<mir::BasicBlock>,
-        cleanup: Option<mir::BasicBlock>,
+        unwind: mir::UnwindAction,
         fn_span: Span,
         mergeable_succ: bool,
     ) -> MergingSucc {
@@ -783,7 +800,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             instance,
             source_info,
             target,
-            cleanup,
+            unwind,
             mergeable_succ,
         ) {
             return merging_succ;
@@ -1064,7 +1081,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 fn_ptr,
                 &llargs,
                 target.as_ref().map(|&target| (ret_dest, target)),
-                cleanup,
+                unwind,
                 &copied_constant_arguments,
                 false,
             );
@@ -1084,7 +1101,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             fn_ptr,
             &llargs,
             target.as_ref().map(|&target| (ret_dest, target)),
-            cleanup,
+            unwind,
             &copied_constant_arguments,
             mergeable_succ,
         )
@@ -1100,7 +1117,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         options: ast::InlineAsmOptions,
         line_spans: &[Span],
         destination: Option<mir::BasicBlock>,
-        cleanup: Option<mir::BasicBlock>,
+        unwind: mir::UnwindAction,
         instance: Instance<'_>,
         mergeable_succ: bool,
     ) -> MergingSucc {
@@ -1164,7 +1181,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             options,
             line_spans,
             destination,
-            cleanup,
+            unwind,
             instance,
             mergeable_succ,
         )
@@ -1246,8 +1263,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 MergingSucc::False
             }
 
-            mir::TerminatorKind::Abort => {
-                self.codegen_abort_terminator(helper, bx, terminator);
+            mir::TerminatorKind::Terminate => {
+                self.codegen_terminate_terminator(helper, bx, terminator);
                 MergingSucc::False
             }
 
@@ -1274,7 +1291,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 self.codegen_drop_terminator(helper, bx, place, target, unwind, mergeable_succ())
             }
 
-            mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => self
+            mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, unwind } => self
                 .codegen_assert_terminator(
                     helper,
                     bx,
@@ -1283,7 +1300,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     expected,
                     msg,
                     target,
-                    cleanup,
+                    unwind,
                     mergeable_succ(),
                 ),
 
@@ -1292,7 +1309,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 ref args,
                 destination,
                 target,
-                cleanup,
+                unwind,
                 from_hir_call: _,
                 fn_span,
             } => self.codegen_call_terminator(
@@ -1303,7 +1320,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 args,
                 destination,
                 target,
-                cleanup,
+                unwind,
                 fn_span,
                 mergeable_succ(),
             ),
@@ -1320,7 +1337,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 options,
                 line_spans,
                 destination,
-                cleanup,
+                unwind,
             } => self.codegen_asm_terminator(
                 helper,
                 bx,
@@ -1330,7 +1347,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 options,
                 line_spans,
                 destination,
-                cleanup,
+                unwind,
                 self.instance,
                 mergeable_succ(),
             ),
@@ -1536,62 +1553,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     fn landing_pad_for_uncached(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock {
         let llbb = self.llbb(bb);
         if base::wants_msvc_seh(self.cx.sess()) {
-            let funclet;
-            let ret_llbb;
-            match self.mir[bb].terminator.as_ref().map(|t| &t.kind) {
-                // This is a basic block that we're aborting the program for,
-                // notably in an `extern` function. These basic blocks are inserted
-                // so that we assert that `extern` functions do indeed not panic,
-                // and if they do we abort the process.
-                //
-                // On MSVC these are tricky though (where we're doing funclets). If
-                // we were to do a cleanuppad (like below) the normal functions like
-                // `longjmp` would trigger the abort logic, terminating the
-                // program. Instead we insert the equivalent of `catch(...)` for C++
-                // which magically doesn't trigger when `longjmp` files over this
-                // frame.
-                //
-                // Lots more discussion can be found on #48251 but this codegen is
-                // modeled after clang's for:
-                //
-                //      try {
-                //          foo();
-                //      } catch (...) {
-                //          bar();
-                //      }
-                Some(&mir::TerminatorKind::Abort) => {
-                    let cs_llbb =
-                        Bx::append_block(self.cx, self.llfn, &format!("cs_funclet{:?}", bb));
-                    let cp_llbb =
-                        Bx::append_block(self.cx, self.llfn, &format!("cp_funclet{:?}", bb));
-                    ret_llbb = cs_llbb;
-
-                    let mut cs_bx = Bx::build(self.cx, cs_llbb);
-                    let cs = cs_bx.catch_switch(None, None, &[cp_llbb]);
-
-                    // The "null" here is actually a RTTI type descriptor for the
-                    // C++ personality function, but `catch (...)` has no type so
-                    // it's null. The 64 here is actually a bitfield which
-                    // represents that this is a catch-all block.
-                    let mut cp_bx = Bx::build(self.cx, cp_llbb);
-                    let null = cp_bx.const_null(
-                        cp_bx.type_i8p_ext(cp_bx.cx().data_layout().instruction_address_space),
-                    );
-                    let sixty_four = cp_bx.const_i32(64);
-                    funclet = cp_bx.catch_pad(cs, &[null, sixty_four, null]);
-                    cp_bx.br(llbb);
-                }
-                _ => {
-                    let cleanup_llbb =
-                        Bx::append_block(self.cx, self.llfn, &format!("funclet_{:?}", bb));
-                    ret_llbb = cleanup_llbb;
-                    let mut cleanup_bx = Bx::build(self.cx, cleanup_llbb);
-                    funclet = cleanup_bx.cleanup_pad(None, &[]);
-                    cleanup_bx.br(llbb);
-                }
-            }
+            let cleanup_bb = Bx::append_block(self.cx, self.llfn, &format!("funclet_{:?}", bb));
+            let mut cleanup_bx = Bx::build(self.cx, cleanup_bb);
+            let funclet = cleanup_bx.cleanup_pad(None, &[]);
+            cleanup_bx.br(llbb);
             self.funclets[bb] = Some(funclet);
-            ret_llbb
+            cleanup_bb
         } else {
             let cleanup_llbb = Bx::append_block(self.cx, self.llfn, "cleanup");
             let mut cleanup_bx = Bx::build(self.cx, cleanup_llbb);
@@ -1618,26 +1585,68 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         })
     }
 
-    fn double_unwind_guard(&mut self) -> Bx::BasicBlock {
-        self.double_unwind_guard.unwrap_or_else(|| {
-            assert!(!base::wants_msvc_seh(self.cx.sess()));
+    fn terminate_block(&mut self) -> Bx::BasicBlock {
+        self.terminate_block.unwrap_or_else(|| {
+            let funclet;
+            let llbb;
+            let mut bx;
+            if base::wants_msvc_seh(self.cx.sess()) {
+                // This is a basic block that we're aborting the program for,
+                // notably in an `extern` function. These basic blocks are inserted
+                // so that we assert that `extern` functions do indeed not panic,
+                // and if they do we abort the process.
+                //
+                // On MSVC these are tricky though (where we're doing funclets). If
+                // we were to do a cleanuppad (like below) the normal functions like
+                // `longjmp` would trigger the abort logic, terminating the
+                // program. Instead we insert the equivalent of `catch(...)` for C++
+                // which magically doesn't trigger when `longjmp` files over this
+                // frame.
+                //
+                // Lots more discussion can be found on #48251 but this codegen is
+                // modeled after clang's for:
+                //
+                //      try {
+                //          foo();
+                //      } catch (...) {
+                //          bar();
+                //      }
+                llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate");
+                let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate");
+
+                let mut cs_bx = Bx::build(self.cx, llbb);
+                let cs = cs_bx.catch_switch(None, None, &[cp_llbb]);
+
+                // The "null" here is actually a RTTI type descriptor for the
+                // C++ personality function, but `catch (...)` has no type so
+                // it's null. The 64 here is actually a bitfield which
+                // represents that this is a catch-all block.
+                bx = Bx::build(self.cx, cp_llbb);
+                let null =
+                    bx.const_null(bx.type_i8p_ext(bx.cx().data_layout().instruction_address_space));
+                let sixty_four = bx.const_i32(64);
+                funclet = Some(bx.catch_pad(cs, &[null, sixty_four, null]));
+            } else {
+                llbb = Bx::append_block(self.cx, self.llfn, "terminate");
+                bx = Bx::build(self.cx, llbb);
+
+                let llpersonality = self.cx.eh_personality();
+                bx.cleanup_landing_pad(llpersonality);
 
-            let llbb = Bx::append_block(self.cx, self.llfn, "abort");
-            let mut bx = Bx::build(self.cx, llbb);
-            self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span));
+                funclet = None;
+            }
 
-            let llpersonality = self.cx.eh_personality();
-            bx.cleanup_landing_pad(llpersonality);
+            self.set_debug_loc(&mut bx, mir::SourceInfo::outermost(self.mir.span));
 
             let (fn_abi, fn_ptr) = common::build_langcall(&bx, None, LangItem::PanicCannotUnwind);
             let fn_ty = bx.fn_decl_backend_type(&fn_abi);
 
-            let llret = bx.call(fn_ty, Some(&fn_abi), fn_ptr, &[], None);
+            let llret = bx.call(fn_ty, Some(&fn_abi), fn_ptr, &[], funclet.as_ref());
             bx.do_not_inline(llret);
 
             bx.unreachable();
 
-            self.double_unwind_guard = Some(llbb);
+            self.terminate_block = Some(llbb);
             llbb
         })
     }
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 189549953d9..3dadb33c969 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -73,8 +73,8 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
     /// Cached unreachable block
     unreachable_block: Option<Bx::BasicBlock>,
 
-    /// Cached double unwind guarding block
-    double_unwind_guard: Option<Bx::BasicBlock>,
+    /// Cached terminate upon unwinding block
+    terminate_block: Option<Bx::BasicBlock>,
 
     /// The location where each MIR arg/var/tmp/ret is stored. This is
     /// usually an `PlaceRef` representing an alloca, but not always:
@@ -166,7 +166,9 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     let start_llbb = Bx::append_block(cx, llfn, "start");
     let mut start_bx = Bx::build(cx, start_llbb);
 
-    if mir.basic_blocks.iter().any(|bb| bb.is_cleanup) {
+    if mir.basic_blocks.iter().any(|bb| {
+        bb.is_cleanup || matches!(bb.terminator().unwind(), Some(mir::UnwindAction::Terminate))
+    }) {
         start_bx.set_personality_fn(cx.eh_personality());
     }
 
@@ -189,7 +191,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         personality_slot: None,
         cached_llbbs,
         unreachable_block: None,
-        double_unwind_guard: None,
+        terminate_block: None,
         cleanup_kinds,
         landing_pads: IndexVec::from_elem(None, &mir.basic_blocks),
         funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks.len()),
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index c87ea18af4f..a5dfd1072f0 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -23,7 +23,7 @@ use rustc_target::spec::abi::Abi as CallAbi;
 
 use crate::interpret::{
     self, compile_time_machine, AllocId, ConstAllocation, FnVal, Frame, ImmTy, InterpCx,
-    InterpResult, OpTy, PlaceTy, Pointer, Scalar, StackPopUnwind,
+    InterpResult, OpTy, PlaceTy, Pointer, Scalar,
 };
 
 use super::error::*;
@@ -271,7 +271,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
                         /* with_caller_location = */ false,
                         dest,
                         ret,
-                        StackPopUnwind::NotAllowed,
+                        mir::UnwindAction::Unreachable,
                     )?;
                     Ok(ControlFlow::Break(()))
                 } else {
@@ -401,7 +401,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         args: &[OpTy<'tcx>],
         dest: &PlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
-        _unwind: StackPopUnwind, // unwinding is not supported in consts
+        _unwind: mir::UnwindAction, // unwinding is not supported in consts
     ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
         debug!("find_mir_or_eval_fn: {:?}", instance);
 
@@ -450,7 +450,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         args: &[OpTy<'tcx>],
         dest: &PlaceTy<'tcx, Self::Provenance>,
         target: Option<mir::BasicBlock>,
-        _unwind: StackPopUnwind,
+        _unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         // Shared intrinsics.
         if ecx.emulate_intrinsic(instance, args, dest, target)? {
@@ -526,7 +526,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
     fn assert_panic(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         msg: &AssertMessage<'tcx>,
-        _unwind: Option<mir::BasicBlock>,
+        _unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         use rustc_middle::mir::AssertKind::*;
         // Convert `AssertKind<Operand>` to `AssertKind<Scalar>`.
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 0918ffcd982..3e58a58aef7 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -139,17 +139,6 @@ pub struct FrameInfo<'tcx> {
     pub lint_root: Option<hir::HirId>,
 }
 
-/// Unwind information.
-#[derive(Clone, Copy, Eq, PartialEq, Debug)]
-pub enum StackPopUnwind {
-    /// The cleanup block.
-    Cleanup(mir::BasicBlock),
-    /// No cleanup needs to be done.
-    Skip,
-    /// Unwinding is not allowed (UB).
-    NotAllowed,
-}
-
 #[derive(Clone, Copy, Eq, PartialEq, Debug)] // Miri debug-prints these
 pub enum StackPopCleanup {
     /// Jump to the next block in the caller, or cause UB if None (that's a function
@@ -157,7 +146,7 @@ pub enum StackPopCleanup {
     /// we can validate it at that layout.
     /// `ret` stores the block we jump to on a normal return, while `unwind`
     /// stores the block used for cleanup during unwinding.
-    Goto { ret: Option<mir::BasicBlock>, unwind: StackPopUnwind },
+    Goto { ret: Option<mir::BasicBlock>, unwind: mir::UnwindAction },
     /// The root frame of the stack: nowhere else to jump to.
     /// `cleanup` says whether locals are deallocated. Static computation
     /// wants them leaked to intern what they need (and just throw away
@@ -735,18 +724,22 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// *Unwind* to the given `target` basic block.
     /// Do *not* use for returning! Use `return_to_block` instead.
     ///
-    /// If `target` is `StackPopUnwind::Skip`, that indicates the function does not need cleanup
+    /// If `target` is `UnwindAction::Continue`, that indicates the function does not need cleanup
     /// during unwinding, and we will just keep propagating that upwards.
     ///
-    /// If `target` is `StackPopUnwind::NotAllowed`, that indicates the function does not allow
+    /// If `target` is `UnwindAction::Unreachable`, that indicates the function does not allow
     /// unwinding, and doing so is UB.
-    pub fn unwind_to_block(&mut self, target: StackPopUnwind) -> InterpResult<'tcx> {
+    pub fn unwind_to_block(&mut self, target: mir::UnwindAction) -> InterpResult<'tcx> {
         self.frame_mut().loc = match target {
-            StackPopUnwind::Cleanup(block) => Left(mir::Location { block, statement_index: 0 }),
-            StackPopUnwind::Skip => Right(self.frame_mut().body.span),
-            StackPopUnwind::NotAllowed => {
+            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")
             }
+            mir::UnwindAction::Terminate => {
+                self.frame_mut().loc = Right(self.frame_mut().body.span);
+                M::abort(self, "panic in a function that cannot unwind".to_owned())?;
+            }
         };
         Ok(())
     }
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index aca68dc454b..0291cca7378 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -18,7 +18,7 @@ use crate::const_eval::CheckAlignment;
 
 use super::{
     AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx,
-    InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind,
+    InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar,
 };
 
 /// Data returned by Machine::stack_pop,
@@ -185,7 +185,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
         args: &[OpTy<'tcx, Self::Provenance>],
         destination: &PlaceTy<'tcx, Self::Provenance>,
         target: Option<mir::BasicBlock>,
-        unwind: StackPopUnwind,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>>;
 
     /// Execute `fn_val`. It is the hook's responsibility to advance the instruction
@@ -197,7 +197,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
         args: &[OpTy<'tcx, Self::Provenance>],
         destination: &PlaceTy<'tcx, Self::Provenance>,
         target: Option<mir::BasicBlock>,
-        unwind: StackPopUnwind,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx>;
 
     /// Directly process an intrinsic without pushing a stack frame. It is the hook's
@@ -208,17 +208,17 @@ pub trait Machine<'mir, 'tcx>: Sized {
         args: &[OpTy<'tcx, Self::Provenance>],
         destination: &PlaceTy<'tcx, Self::Provenance>,
         target: Option<mir::BasicBlock>,
-        unwind: StackPopUnwind,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx>;
 
     /// Called to evaluate `Assert` MIR terminators that trigger a panic.
     fn assert_panic(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         msg: &mir::AssertMessage<'tcx>,
-        unwind: Option<mir::BasicBlock>,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx>;
 
-    /// Called to evaluate `Abort` MIR terminator.
+    /// Called to abort evaluation.
     fn abort(_ecx: &mut InterpCx<'mir, 'tcx, Self>, _msg: String) -> InterpResult<'tcx, !> {
         throw_unsup_format!("aborting execution is not supported")
     }
@@ -487,7 +487,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
         _args: &[OpTy<$tcx>],
         _destination: &PlaceTy<$tcx, Self::Provenance>,
         _target: Option<mir::BasicBlock>,
-        _unwind: StackPopUnwind,
+        _unwind: mir::UnwindAction,
     ) -> InterpResult<$tcx> {
         match fn_val {}
     }
diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs
index 86de4e4e32c..898d62361ab 100644
--- a/compiler/rustc_const_eval/src/interpret/mod.rs
+++ b/compiler/rustc_const_eval/src/interpret/mod.rs
@@ -20,9 +20,7 @@ mod visitor;
 
 pub use rustc_middle::mir::interpret::*; // have all the `interpret` symbols in one place: here
 
-pub use self::eval_context::{
-    Frame, FrameInfo, InterpCx, LocalState, LocalValue, StackPopCleanup, StackPopUnwind,
-};
+pub use self::eval_context::{Frame, FrameInfo, InterpCx, LocalState, LocalValue, StackPopCleanup};
 pub use self::intern::{intern_const_alloc_recursive, InternKind};
 pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackPopJump};
 pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind};
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 2d9fee9852c..a07702f7d9b 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -13,7 +13,7 @@ use rustc_target::spec::abi::Abi;
 
 use super::{
     FnVal, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemoryKind, OpTy, Operand,
-    PlaceTy, Scalar, StackPopCleanup, StackPopUnwind,
+    PlaceTy, Scalar, StackPopCleanup,
 };
 
 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
@@ -60,7 +60,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 ref args,
                 destination,
                 target,
-                ref cleanup,
+                unwind,
                 from_hir_call: _,
                 fn_span: _,
             } => {
@@ -106,11 +106,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     with_caller_location,
                     &destination,
                     target,
-                    match (cleanup, fn_abi.can_unwind) {
-                        (Some(cleanup), true) => StackPopUnwind::Cleanup(*cleanup),
-                        (None, true) => StackPopUnwind::Skip,
-                        (_, false) => StackPopUnwind::NotAllowed,
-                    },
+                    if fn_abi.can_unwind { unwind } else { mir::UnwindAction::Unreachable },
                 )?;
                 // Sanity-check that `eval_fn_call` either pushed a new frame or
                 // did a jump to another block.
@@ -137,19 +133,20 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 self.drop_in_place(&place, instance, target, unwind)?;
             }
 
-            Assert { ref cond, expected, ref msg, target, cleanup } => {
+            Assert { ref cond, expected, ref msg, target, unwind } => {
                 let ignored =
                     M::ignore_optional_overflow_checks(self) && msg.is_optional_overflow_check();
                 let cond_val = self.read_scalar(&self.eval_operand(cond, None)?)?.to_bool()?;
                 if ignored || expected == cond_val {
                     self.go_to_block(target);
                 } else {
-                    M::assert_panic(self, msg, cleanup)?;
+                    M::assert_panic(self, msg, unwind)?;
                 }
             }
 
-            Abort => {
-                M::abort(self, "the program aborted execution".to_owned())?;
+            Terminate => {
+                // FIXME: maybe should call `panic_no_unwind` lang item instead.
+                M::abort(self, "panic in a function that cannot unwind".to_owned())?;
             }
 
             // When we encounter Resume, we've finished unwinding
@@ -351,7 +348,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         with_caller_location: bool,
         destination: &PlaceTy<'tcx, M::Provenance>,
         target: Option<mir::BasicBlock>,
-        mut unwind: StackPopUnwind,
+        mut unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         trace!("eval_fn_call: {:#?}", fn_val);
 
@@ -410,9 +407,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     }
                 }
 
-                if !matches!(unwind, StackPopUnwind::NotAllowed) && !callee_fn_abi.can_unwind {
-                    // The callee cannot unwind.
-                    unwind = StackPopUnwind::NotAllowed;
+                if !callee_fn_abi.can_unwind {
+                    // The callee cannot unwind, so force the `Unreachable` unwind handling.
+                    unwind = mir::UnwindAction::Unreachable;
                 }
 
                 self.push_stack_frame(
@@ -676,7 +673,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         place: &PlaceTy<'tcx, M::Provenance>,
         instance: ty::Instance<'tcx>,
         target: mir::BasicBlock,
-        unwind: Option<mir::BasicBlock>,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         trace!("drop_in_place: {:?},\n  {:?}, {:?}", *place, place.layout.ty, instance);
         // We take the address of the object. This may well be unaligned, which is fine
@@ -717,10 +714,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             false,
             &ret.into(),
             Some(target),
-            match unwind {
-                Some(cleanup) => StackPopUnwind::Cleanup(cleanup),
-                None => StackPopUnwind::Skip,
-            },
+            unwind,
         )
     }
 }
diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs
index 16b83af91ac..5ab389d04c7 100644
--- a/compiler/rustc_const_eval/src/lib.rs
+++ b/compiler/rustc_const_eval/src/lib.rs
@@ -20,7 +20,6 @@ Rust MIR: a lowered representation of Rust.
 #![feature(try_blocks)]
 #![feature(yeet_expr)]
 #![feature(if_let_guard)]
-#![feature(is_some_and)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 20c0852fe33..9dad9479053 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -1031,9 +1031,9 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                 self.check_op(ops::Generator(hir::GeneratorKind::Gen))
             }
 
-            TerminatorKind::Abort => {
+            TerminatorKind::Terminate => {
                 // Cleanup blocks are skipped for const checking (see `visit_basic_block_data`).
-                span_bug!(self.span, "`Abort` terminator outside of cleanup block")
+                span_bug!(self.span, "`Terminate` terminator outside of cleanup block")
             }
 
             TerminatorKind::Assert { .. }
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
index f01ab4c5d61..1f1640fd80a 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
@@ -104,7 +104,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
                 }
             }
 
-            mir::TerminatorKind::Abort
+            mir::TerminatorKind::Terminate
             | mir::TerminatorKind::Call { .. }
             | mir::TerminatorKind::Assert { .. }
             | mir::TerminatorKind::FalseEdge { .. }
diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs
index 6774e5a5837..7919aed097a 100644
--- a/compiler/rustc_const_eval/src/transform/promote_consts.rs
+++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs
@@ -807,7 +807,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
                         kind: TerminatorKind::Call {
                             func,
                             args,
-                            cleanup: None,
+                            unwind: UnwindAction::Continue,
                             destination: Place::from(new_temp),
                             target: Some(new_target),
                             from_hir_call,
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index e798c9d236e..0f56fda18f5 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -10,7 +10,7 @@ use rustc_middle::mir::{
     traversal, BasicBlock, BinOp, Body, BorrowKind, CastKind, CopyNonOverlapping, Local, Location,
     MirPass, MirPhase, NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef, ProjectionElem,
     RetagKind, RuntimePhase, Rvalue, SourceScope, Statement, StatementKind, Terminator,
-    TerminatorKind, UnOp, VarDebugInfo, VarDebugInfoContents, START_BLOCK,
+    TerminatorKind, UnOp, UnwindAction, VarDebugInfo, VarDebugInfoContents, START_BLOCK,
 };
 use rustc_middle::ty::{self, InstanceDef, ParamEnv, Ty, TyCtxt, TypeVisitableExt};
 use rustc_mir_dataflow::impls::MaybeStorageLive;
@@ -232,6 +232,24 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         }
     }
 
+    fn check_unwind_edge(&mut self, location: Location, unwind: UnwindAction) {
+        let is_cleanup = self.body.basic_blocks[location.block].is_cleanup;
+        match unwind {
+            UnwindAction::Cleanup(unwind) => {
+                if is_cleanup {
+                    self.fail(location, "unwind on cleanup block");
+                }
+                self.check_edge(location, unwind, EdgeKind::Unwind);
+            }
+            UnwindAction::Continue => {
+                if is_cleanup {
+                    self.fail(location, "unwind on cleanup block");
+                }
+            }
+            UnwindAction::Unreachable | UnwindAction::Terminate => (),
+        }
+    }
+
     /// Check if src can be assigned into dest.
     /// This is not precise, it will accept some incorrect assignments.
     fn mir_assign_valid_types(&self, src: Ty<'tcx>, dest: Ty<'tcx>) -> bool {
@@ -902,11 +920,9 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             }
             TerminatorKind::Drop { target, unwind, .. } => {
                 self.check_edge(location, *target, EdgeKind::Normal);
-                if let Some(unwind) = unwind {
-                    self.check_edge(location, *unwind, EdgeKind::Unwind);
-                }
+                self.check_unwind_edge(location, *unwind);
             }
-            TerminatorKind::Call { func, args, destination, target, cleanup, .. } => {
+            TerminatorKind::Call { func, args, destination, target, unwind, .. } => {
                 let func_ty = func.ty(&self.body.local_decls, self.tcx);
                 match func_ty.kind() {
                     ty::FnPtr(..) | ty::FnDef(..) => {}
@@ -918,9 +934,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                 if let Some(target) = target {
                     self.check_edge(location, *target, EdgeKind::Normal);
                 }
-                if let Some(cleanup) = cleanup {
-                    self.check_edge(location, *cleanup, EdgeKind::Unwind);
-                }
+                self.check_unwind_edge(location, *unwind);
 
                 // The call destination place and Operand::Move place used as an argument might be
                 // passed by a reference to the callee. Consequently they must be non-overlapping.
@@ -946,7 +960,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     );
                 }
             }
-            TerminatorKind::Assert { cond, target, cleanup, .. } => {
+            TerminatorKind::Assert { cond, target, unwind, .. } => {
                 let cond_ty = cond.ty(&self.body.local_decls, self.tcx);
                 if cond_ty != self.tcx.types.bool {
                     self.fail(
@@ -958,9 +972,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     );
                 }
                 self.check_edge(location, *target, EdgeKind::Normal);
-                if let Some(cleanup) = cleanup {
-                    self.check_edge(location, *cleanup, EdgeKind::Unwind);
-                }
+                self.check_unwind_edge(location, *unwind);
             }
             TerminatorKind::Yield { resume, drop, .. } => {
                 if self.body.generator.is_none() {
@@ -992,17 +1004,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     );
                 }
                 self.check_edge(location, *real_target, EdgeKind::Normal);
-                if let Some(unwind) = unwind {
-                    self.check_edge(location, *unwind, EdgeKind::Unwind);
-                }
+                self.check_unwind_edge(location, *unwind);
             }
-            TerminatorKind::InlineAsm { destination, cleanup, .. } => {
+            TerminatorKind::InlineAsm { destination, unwind, .. } => {
                 if let Some(destination) = destination {
                     self.check_edge(location, *destination, EdgeKind::Normal);
                 }
-                if let Some(cleanup) = cleanup {
-                    self.check_edge(location, *cleanup, EdgeKind::Unwind);
-                }
+                self.check_unwind_edge(location, *unwind);
             }
             TerminatorKind::GeneratorDrop => {
                 if self.body.generator.is_none() {
@@ -1015,10 +1023,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     );
                 }
             }
-            TerminatorKind::Resume | TerminatorKind::Abort => {
+            TerminatorKind::Resume | TerminatorKind::Terminate => {
                 let bb = location.block;
                 if !self.body.basic_blocks[bb].is_cleanup {
-                    self.fail(location, "Cannot `Resume` or `Abort` from non-cleanup basic block")
+                    self.fail(
+                        location,
+                        "Cannot `Resume` or `Terminate` from non-cleanup basic block",
+                    )
                 }
             }
             TerminatorKind::Return => {
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 9b52638e612..e373bd18402 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -1,5 +1,5 @@
 //! Various data structures used by the Rust compiler. The intention
-//! is that code in here should be not be *specific* to rustc, so that
+//! is that code in here should not be *specific* to rustc, so that
 //! it can be easily unit tested and so forth.
 //!
 //! # Note
@@ -27,6 +27,8 @@
 #![feature(thread_id_value)]
 #![feature(vec_into_raw_parts)]
 #![feature(get_mut_unchecked)]
+#![feature(lint_reasons)]
+#![feature(unwrap_infallible)]
 #![allow(rustc::default_hash_types)]
 #![allow(rustc::potential_query_instability)]
 #![deny(rustc::untranslatable_diagnostic)]
@@ -59,7 +61,6 @@ pub mod intern;
 pub mod jobserver;
 pub mod macros;
 pub mod obligation_forest;
-pub mod owning_ref;
 pub mod sip128;
 pub mod small_c_str;
 pub mod small_str;
@@ -82,6 +83,7 @@ pub mod vec_linked_list;
 pub mod work_queue;
 pub use atomic_ref::AtomicRef;
 pub mod frozen;
+pub mod owned_slice;
 pub mod sso;
 pub mod steal;
 pub mod tagged_ptr;
diff --git a/compiler/rustc_data_structures/src/memmap.rs b/compiler/rustc_data_structures/src/memmap.rs
index 3d44e17f31d..1556873f597 100644
--- a/compiler/rustc_data_structures/src/memmap.rs
+++ b/compiler/rustc_data_structures/src/memmap.rs
@@ -2,9 +2,7 @@ use std::fs::File;
 use std::io;
 use std::ops::{Deref, DerefMut};
 
-use crate::owning_ref::StableAddress;
-
-/// A trivial wrapper for [`memmap2::Mmap`] that implements [`StableAddress`].
+/// A trivial wrapper for [`memmap2::Mmap`] (or `Vec<u8>` on WASM).
 #[cfg(not(target_arch = "wasm32"))]
 pub struct Mmap(memmap2::Mmap);
 
@@ -46,12 +44,6 @@ impl AsRef<[u8]> for Mmap {
     }
 }
 
-// SAFETY: On architectures other than WASM, mmap is used as backing storage. The address of this
-// memory map is stable. On WASM, `Vec<u8>` is used as backing storage. The `Mmap` type doesn't
-// export any function that can cause the `Vec` to be re-allocated. As such the address of the
-// bytes inside this `Vec` is stable.
-unsafe impl StableAddress for Mmap {}
-
 #[cfg(not(target_arch = "wasm32"))]
 pub struct MmapMut(memmap2::MmapMut);
 
diff --git a/compiler/rustc_data_structures/src/owned_slice.rs b/compiler/rustc_data_structures/src/owned_slice.rs
new file mode 100644
index 00000000000..048401f66c2
--- /dev/null
+++ b/compiler/rustc_data_structures/src/owned_slice.rs
@@ -0,0 +1,118 @@
+use std::{borrow::Borrow, ops::Deref};
+
+// Use our fake Send/Sync traits when on not parallel compiler,
+// so that `OwnedSlice` only implements/requires Send/Sync
+// for parallel compiler builds.
+use crate::sync::{Send, Sync};
+
+/// An owned slice.
+///
+/// This is similar to `Box<[u8]>` but allows slicing and using anything as the
+/// backing buffer.
+///
+/// See [`slice_owned`] for `OwnedSlice` construction and examples.
+///
+/// ---------------------------------------------------------------------------
+///
+/// This is essentially a replacement for `owning_ref` which is a lot simpler
+/// and even sound! 🌸
+pub struct OwnedSlice {
+    /// This is conceptually a `&'self.owner [u8]`.
+    bytes: *const [u8],
+
+    // +---------------------------------------+
+    // | We expect `dead_code` lint here,      |
+    // | because we don't want to accidentally |
+    // | touch the owner — otherwise the owner |
+    // | could invalidate out `bytes` pointer  |
+    // |                                       |
+    // | so be quiet                           |
+    // +----+  +-------------------------------+
+    //       \/
+    //      ⊂(´・◡・⊂ )∘˚˳° (I am the phantom remnant of #97770)
+    #[expect(dead_code)]
+    owner: Box<dyn Send + Sync>,
+}
+
+/// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function.
+///
+/// ## Examples
+///
+/// ```rust
+/// # use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned};
+/// let vec = vec![1, 2, 3, 4];
+///
+/// // Identical to slicing via `&v[1..3]` but produces an owned slice
+/// let slice: OwnedSlice = slice_owned(vec, |v| &v[1..3]);
+/// assert_eq!(&*slice, [2, 3]);
+/// ```
+///
+/// ```rust
+/// # use rustc_data_structures::owned_slice::{OwnedSlice, slice_owned};
+/// # use std::ops::Deref;
+/// let vec = vec![1, 2, 3, 4];
+///
+/// // Identical to slicing via `&v[..]` but produces an owned slice
+/// let slice: OwnedSlice = slice_owned(vec, Deref::deref);
+/// assert_eq!(&*slice, [1, 2, 3, 4]);
+/// ```
+pub fn slice_owned<O, F>(owner: O, slicer: F) -> OwnedSlice
+where
+    O: Send + Sync + 'static,
+    F: FnOnce(&O) -> &[u8],
+{
+    try_slice_owned(owner, |x| Ok::<_, !>(slicer(x))).into_ok()
+}
+
+/// Makes an [`OwnedSlice`] out of an `owner` and a `slicer` function that can fail.
+///
+/// See [`slice_owned`] for the infallible version.
+pub fn try_slice_owned<O, F, E>(owner: O, slicer: F) -> Result<OwnedSlice, E>
+where
+    O: Send + Sync + 'static,
+    F: FnOnce(&O) -> Result<&[u8], E>,
+{
+    // We box the owner of the bytes, so it doesn't move.
+    //
+    // Since the owner does not move and we don't access it in any way
+    // before drop, there is nothing that can invalidate the bytes pointer.
+    //
+    // Thus, "extending" the lifetime of the reference returned from `F` is fine.
+    // We pretend that we pass it a reference that lives as long as the returned slice.
+    //
+    // N.B. the HRTB on the `slicer` is important — without it the caller could provide
+    // a short lived slice, unrelated to the owner.
+
+    let owner = Box::new(owner);
+    let bytes = slicer(&*owner)?;
+
+    Ok(OwnedSlice { bytes, owner })
+}
+
+impl Deref for OwnedSlice {
+    type Target = [u8];
+
+    #[inline]
+    fn deref(&self) -> &[u8] {
+        // Safety:
+        // `self.bytes` is valid per the construction in `slice_owned`
+        // (which is the only constructor)
+        unsafe { &*self.bytes }
+    }
+}
+
+impl Borrow<[u8]> for OwnedSlice {
+    #[inline]
+    fn borrow(&self) -> &[u8] {
+        self
+    }
+}
+
+// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Box<dyn Send + Sync>)`, which is `Send`
+unsafe impl Send for OwnedSlice {}
+
+// Safety: `OwnedSlice` is conceptually `(&'self.1 [u8], Box<dyn Send + Sync>)`, which is `Sync`
+unsafe impl Sync for OwnedSlice {}
+
+#[cfg(test)]
+mod tests;
diff --git a/compiler/rustc_data_structures/src/owned_slice/tests.rs b/compiler/rustc_data_structures/src/owned_slice/tests.rs
new file mode 100644
index 00000000000..e715fb55362
--- /dev/null
+++ b/compiler/rustc_data_structures/src/owned_slice/tests.rs
@@ -0,0 +1,74 @@
+use std::{
+    ops::Deref,
+    sync::{
+        atomic::{self, AtomicBool},
+        Arc,
+    },
+};
+
+use crate::{
+    owned_slice::{slice_owned, try_slice_owned, OwnedSlice},
+    OnDrop,
+};
+
+#[test]
+fn smoke() {
+    let slice = slice_owned(vec![1, 2, 3, 4, 5, 6], Vec::as_slice);
+
+    assert_eq!(&*slice, [1, 2, 3, 4, 5, 6]);
+}
+
+#[test]
+fn static_storage() {
+    let slice = slice_owned(Box::new(String::from("what")), |_| b"bytes boo");
+
+    assert_eq!(&*slice, b"bytes boo");
+}
+
+#[test]
+fn slice_the_slice() {
+    let slice = slice_owned(vec![1, 2, 3, 4, 5, 6], Vec::as_slice);
+    let slice = slice_owned(slice, |s| &s[1..][..4]);
+    let slice = slice_owned(slice, |s| s);
+    let slice = slice_owned(slice, |s| &s[1..]);
+
+    assert_eq!(&*slice, &[1, 2, 3, 4, 5, 6][1..][..4][1..]);
+}
+
+#[test]
+fn try_and_fail() {
+    let res = try_slice_owned(vec![0], |v| v.get(12..).ok_or(()));
+
+    assert!(res.is_err());
+}
+
+#[test]
+fn boxed() {
+    // It's important that we don't cause UB because of `Box`'es uniqueness
+
+    let boxed: Box<[u8]> = vec![1, 1, 2, 3, 5, 8, 13, 21].into_boxed_slice();
+    let slice = slice_owned(boxed, Deref::deref);
+
+    assert_eq!(&*slice, [1, 1, 2, 3, 5, 8, 13, 21]);
+}
+
+#[test]
+fn drop_drops() {
+    let flag = Arc::new(AtomicBool::new(false));
+    let flag_prime = Arc::clone(&flag);
+    let d = OnDrop(move || flag_prime.store(true, atomic::Ordering::Relaxed));
+
+    let slice = slice_owned(d, |_| &[]);
+
+    assert_eq!(flag.load(atomic::Ordering::Relaxed), false);
+
+    drop(slice);
+
+    assert_eq!(flag.load(atomic::Ordering::Relaxed), true);
+}
+
+#[test]
+fn send_sync() {
+    crate::sync::assert_send::<OwnedSlice>();
+    crate::sync::assert_sync::<OwnedSlice>();
+}
diff --git a/compiler/rustc_data_structures/src/owning_ref/LICENSE b/compiler/rustc_data_structures/src/owning_ref/LICENSE
deleted file mode 100644
index dff72d1e432..00000000000
--- a/compiler/rustc_data_structures/src/owning_ref/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2015 Marvin Löbel
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/compiler/rustc_data_structures/src/owning_ref/mod.rs b/compiler/rustc_data_structures/src/owning_ref/mod.rs
deleted file mode 100644
index d1d92b905b8..00000000000
--- a/compiler/rustc_data_structures/src/owning_ref/mod.rs
+++ /dev/null
@@ -1,1211 +0,0 @@
-#![warn(missing_docs)]
-
-/*!
-# An owning reference.
-
-This crate provides the _owning reference_ types `OwningRef` and `OwningRefMut`
-that enables it to bundle a reference together with the owner of the data it points to.
-This allows moving and dropping of an `OwningRef` without needing to recreate the reference.
-
-This can sometimes be useful because Rust borrowing rules normally prevent
-moving a type that has been moved from. For example, this kind of code gets rejected:
-
-```compile_fail,E0515
-fn return_owned_and_referenced<'a>() -> (Vec<u8>, &'a [u8]) {
-    let v = vec![1, 2, 3, 4];
-    let s = &v[1..3];
-    (v, s)
-}
-```
-
-Even though, from a memory-layout point of view, this can be entirely safe
-if the new location of the vector still lives longer than the lifetime `'a`
-of the reference because the backing allocation of the vector does not change.
-
-This library enables this safe usage by keeping the owner and the reference
-bundled together in a wrapper type that ensure that lifetime constraint:
-
-```
-# use rustc_data_structures::owning_ref::OwningRef;
-# fn main() {
-fn return_owned_and_referenced() -> OwningRef<Vec<u8>, [u8]> {
-    let v = vec![1, 2, 3, 4];
-    let or = OwningRef::new(v);
-    let or = or.map(|v| &v[1..3]);
-    or
-}
-# }
-```
-
-It works by requiring owner types to dereference to stable memory locations
-and preventing mutable access to root containers, which in practice requires heap allocation
-as provided by `Box<T>`, `Rc<T>`, etc.
-
-Also provided are typedefs for common owner type combinations,
-which allow for less verbose type signatures.
-For example, `BoxRef<T>` instead of `OwningRef<Box<T>, T>`.
-
-The crate also provides the more advanced `OwningHandle` type,
-which allows more freedom in bundling a dependent handle object
-along with the data it depends on, at the cost of some unsafe needed in the API.
-See the documentation around `OwningHandle` for more details.
-
-# Examples
-
-## Basics
-
-```
-use rustc_data_structures::owning_ref::BoxRef;
-
-fn main() {
-    // Create an array owned by a Box.
-    let arr = Box::new([1, 2, 3, 4]) as Box<[i32]>;
-
-    // Transfer into a BoxRef.
-    let arr: BoxRef<[i32]> = BoxRef::new(arr);
-    assert_eq!(&*arr, &[1, 2, 3, 4]);
-
-    // We can slice the array without losing ownership or changing type.
-    let arr: BoxRef<[i32]> = arr.map(|arr| &arr[1..3]);
-    assert_eq!(&*arr, &[2, 3]);
-
-    // Also works for Arc, Rc, String and Vec!
-}
-```
-
-## Caching a reference to a struct field
-
-```
-use rustc_data_structures::owning_ref::BoxRef;
-
-fn main() {
-    struct Foo {
-        tag: u32,
-        x: u16,
-        y: u16,
-        z: u16,
-    }
-    let foo = Foo { tag: 1, x: 100, y: 200, z: 300 };
-
-    let or = BoxRef::new(Box::new(foo)).map(|foo| {
-        match foo.tag {
-            0 => &foo.x,
-            1 => &foo.y,
-            2 => &foo.z,
-            _ => panic!(),
-        }
-    });
-
-    assert_eq!(*or, 200);
-}
-```
-
-## Caching a reference to an entry in a vector
-
-```
-use rustc_data_structures::owning_ref::VecRef;
-
-fn main() {
-    let v = VecRef::new(vec![1, 2, 3, 4, 5]).map(|v| &v[3]);
-    assert_eq!(*v, 4);
-}
-```
-
-## Caching a subslice of a String
-
-```
-use rustc_data_structures::owning_ref::StringRef;
-
-fn main() {
-    let s = StringRef::new("hello world".to_owned())
-        .map(|s| s.split(' ').nth(1).unwrap());
-
-    assert_eq!(&*s, "world");
-}
-```
-
-## Reference counted slices that share ownership of the backing storage
-
-```
-use rustc_data_structures::owning_ref::RcRef;
-use std::rc::Rc;
-
-fn main() {
-    let rc: RcRef<[i32]> = RcRef::new(Rc::new([1, 2, 3, 4]) as Rc<[i32]>);
-    assert_eq!(&*rc, &[1, 2, 3, 4]);
-
-    let rc_a: RcRef<[i32]> = rc.clone().map(|s| &s[0..2]);
-    let rc_b = rc.clone().map(|s| &s[1..3]);
-    let rc_c = rc.clone().map(|s| &s[2..4]);
-    assert_eq!(&*rc_a, &[1, 2]);
-    assert_eq!(&*rc_b, &[2, 3]);
-    assert_eq!(&*rc_c, &[3, 4]);
-
-    let rc_c_a = rc_c.clone().map(|s| &s[1]);
-    assert_eq!(&*rc_c_a, &4);
-}
-```
-
-## Atomic reference counted slices that share ownership of the backing storage
-
-```
-use rustc_data_structures::owning_ref::ArcRef;
-use std::sync::Arc;
-
-fn main() {
-    use std::thread;
-
-    fn par_sum(rc: ArcRef<[i32]>) -> i32 {
-        if rc.len() == 0 {
-            return 0;
-        } else if rc.len() == 1 {
-            return rc[0];
-        }
-        let mid = rc.len() / 2;
-        let left = rc.clone().map(|s| &s[..mid]);
-        let right = rc.map(|s| &s[mid..]);
-
-        let left = thread::spawn(move || par_sum(left));
-        let right = thread::spawn(move || par_sum(right));
-
-        left.join().unwrap() + right.join().unwrap()
-    }
-
-    let rc: Arc<[i32]> = Arc::new([1, 2, 3, 4]);
-    let rc: ArcRef<[i32]> = rc.into();
-
-    assert_eq!(par_sum(rc), 10);
-}
-```
-
-## References into RAII locks
-
-```
-use rustc_data_structures::owning_ref::RefRef;
-use std::cell::{RefCell, Ref};
-
-fn main() {
-    let refcell = RefCell::new((1, 2, 3, 4));
-    // Also works with Mutex and RwLock
-
-    let refref = {
-        let refref = RefRef::new(refcell.borrow()).map(|x| &x.3);
-        assert_eq!(*refref, 4);
-
-        // We move the RAII lock and the reference to one of
-        // the subfields in the data it guards here:
-        refref
-    };
-
-    assert_eq!(*refref, 4);
-
-    drop(refref);
-
-    assert_eq!(*refcell.borrow(), (1, 2, 3, 4));
-}
-```
-
-## Mutable reference
-
-When the owned container implements `DerefMut`, it is also possible to make
-a _mutable owning reference_. (e.g., with `Box`, `RefMut`, `MutexGuard`)
-
-```
-use rustc_data_structures::owning_ref::RefMutRefMut;
-use std::cell::{RefCell, RefMut};
-
-fn main() {
-    let refcell = RefCell::new((1, 2, 3, 4));
-
-    let mut refmut_refmut = {
-        let mut refmut_refmut = RefMutRefMut::new(refcell.borrow_mut()).map_mut(|x| &mut x.3);
-        assert_eq!(*refmut_refmut, 4);
-        *refmut_refmut *= 2;
-
-        refmut_refmut
-    };
-
-    assert_eq!(*refmut_refmut, 8);
-    *refmut_refmut *= 2;
-
-    drop(refmut_refmut);
-
-    assert_eq!(*refcell.borrow(), (1, 2, 3, 16));
-}
-```
-*/
-
-pub use stable_deref_trait::{
-    CloneStableDeref as CloneStableAddress, StableDeref as StableAddress,
-};
-use std::mem;
-
-/// An owning reference.
-///
-/// This wraps an owner `O` and a reference `&T` pointing
-/// at something reachable from `O::Target` while keeping
-/// the ability to move `self` around.
-///
-/// The owner is usually a pointer that points at some base type.
-///
-/// For more details and examples, see the module and method docs.
-pub struct OwningRef<O, T: ?Sized> {
-    owner: O,
-    reference: *const T,
-}
-
-/// An mutable owning reference.
-///
-/// This wraps an owner `O` and a reference `&mut T` pointing
-/// at something reachable from `O::Target` while keeping
-/// the ability to move `self` around.
-///
-/// The owner is usually a pointer that points at some base type.
-///
-/// For more details and examples, see the module and method docs.
-pub struct OwningRefMut<O, T: ?Sized> {
-    owner: O,
-    reference: *mut T,
-}
-
-/// Helper trait for an erased concrete type an owner dereferences to.
-/// This is used in form of a trait object for keeping
-/// something around to (virtually) call the destructor.
-pub trait Erased {}
-impl<T> Erased for T {}
-
-/// Helper trait for erasing the concrete type of what an owner dereferences to,
-/// for example `Box<T> -> Box<Erased>`. This would be unneeded with
-/// higher kinded types support in the language.
-#[allow(unused_lifetimes)]
-pub unsafe trait IntoErased<'a> {
-    /// Owner with the dereference type substituted to `Erased`.
-    type Erased;
-    /// Performs the type erasure.
-    fn into_erased(self) -> Self::Erased;
-}
-
-/// Helper trait for erasing the concrete type of what an owner dereferences to,
-/// for example `Box<T> -> Box<Erased + Send>`. This would be unneeded with
-/// higher kinded types support in the language.
-#[allow(unused_lifetimes)]
-pub unsafe trait IntoErasedSend<'a> {
-    /// Owner with the dereference type substituted to `Erased + Send`.
-    type Erased: Send;
-    /// Performs the type erasure.
-    fn into_erased_send(self) -> Self::Erased;
-}
-
-/// Helper trait for erasing the concrete type of what an owner dereferences to,
-/// for example `Box<T> -> Box<Erased + Send + Sync>`. This would be unneeded with
-/// higher kinded types support in the language.
-#[allow(unused_lifetimes)]
-pub unsafe trait IntoErasedSendSync<'a> {
-    /// Owner with the dereference type substituted to `Erased + Send + Sync`.
-    type Erased: Send + Sync;
-    /// Performs the type erasure.
-    fn into_erased_send_sync(self) -> Self::Erased;
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// OwningRef
-/////////////////////////////////////////////////////////////////////////////
-
-impl<O, T: ?Sized> OwningRef<O, T> {
-    /// Creates a new owning reference from an owner
-    /// initialized to the direct dereference of it.
-    ///
-    /// # Example
-    /// ```
-    /// use rustc_data_structures::owning_ref::OwningRef;
-    ///
-    /// fn main() {
-    ///     let owning_ref = OwningRef::new(Box::new(42));
-    ///     assert_eq!(*owning_ref, 42);
-    /// }
-    /// ```
-    pub fn new(o: O) -> Self
-    where
-        O: StableAddress,
-        O: Deref<Target = T>,
-    {
-        OwningRef { reference: &*o, owner: o }
-    }
-
-    /// Like `new`, but doesn’t require `O` to implement the `StableAddress` trait.
-    /// Instead, the caller is responsible to make the same promises as implementing the trait.
-    ///
-    /// This is useful for cases where coherence rules prevents implementing the trait
-    /// without adding a dependency to this crate in a third-party library.
-    pub unsafe fn new_assert_stable_address(o: O) -> Self
-    where
-        O: Deref<Target = T>,
-    {
-        OwningRef { reference: &*o, owner: o }
-    }
-
-    /// Converts `self` into a new owning reference that points at something reachable
-    /// from the previous one.
-    ///
-    /// This can be a reference to a field of `U`, something reachable from a field of
-    /// `U`, or even something unrelated with a `'static` lifetime.
-    ///
-    /// # Example
-    /// ```
-    /// use rustc_data_structures::owning_ref::OwningRef;
-    ///
-    /// fn main() {
-    ///     let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4]));
-    ///
-    ///     // create an owning reference that points at the
-    ///     // third element of the array.
-    ///     let owning_ref = owning_ref.map(|array| &array[2]);
-    ///     assert_eq!(*owning_ref, 3);
-    /// }
-    /// ```
-    pub fn map<F, U: ?Sized>(self, f: F) -> OwningRef<O, U>
-    where
-        O: StableAddress,
-        F: FnOnce(&T) -> &U,
-    {
-        OwningRef { reference: f(&self), owner: self.owner }
-    }
-
-    /// Tries to convert `self` into a new owning reference that points
-    /// at something reachable from the previous one.
-    ///
-    /// This can be a reference to a field of `U`, something reachable from a field of
-    /// `U`, or even something unrelated with a `'static` lifetime.
-    ///
-    /// # Example
-    /// ```
-    /// use rustc_data_structures::owning_ref::OwningRef;
-    ///
-    /// fn main() {
-    ///     let owning_ref = OwningRef::new(Box::new([1, 2, 3, 4]));
-    ///
-    ///     // create an owning reference that points at the
-    ///     // third element of the array.
-    ///     let owning_ref = owning_ref.try_map(|array| {
-    ///         if array[2] == 3 { Ok(&array[2]) } else { Err(()) }
-    ///     });
-    ///     assert_eq!(*owning_ref.unwrap(), 3);
-    /// }
-    /// ```
-    pub fn try_map<F, U: ?Sized, E>(self, f: F) -> Result<OwningRef<O, U>, E>
-    where
-        O: StableAddress,
-        F: FnOnce(&T) -> Result<&U, E>,
-    {
-        Ok(OwningRef { reference: f(&self)?, owner: self.owner })
-    }
-
-    /// Converts `self` into a new owning reference with a different owner type.
-    ///
-    /// The new owner type needs to still contain the original owner in some way
-    /// so that the reference into it remains valid. This function is marked unsafe
-    /// because the user needs to manually uphold this guarantee.
-    pub unsafe fn map_owner<F, P>(self, f: F) -> OwningRef<P, T>
-    where
-        O: StableAddress,
-        P: StableAddress,
-        F: FnOnce(O) -> P,
-    {
-        OwningRef { reference: self.reference, owner: f(self.owner) }
-    }
-
-    /// Converts `self` into a new owning reference where the owner is wrapped
-    /// in an additional `Box<O>`.
-    ///
-    /// This can be used to safely erase the owner of any `OwningRef<O, T>`
-    /// to an `OwningRef<Box<Erased>, T>`.
-    pub fn map_owner_box(self) -> OwningRef<Box<O>, T> {
-        OwningRef { reference: self.reference, owner: Box::new(self.owner) }
-    }
-
-    /// Erases the concrete base type of the owner with a trait object.
-    ///
-    /// This allows mixing of owned references with different owner base types.
-    ///
-    /// # Example
-    /// ```
-    /// use rustc_data_structures::owning_ref::{OwningRef, Erased};
-    ///
-    /// fn main() {
-    ///     // N.B., using the concrete types here for explicitness.
-    ///     // For less verbose code type aliases like `BoxRef` are provided.
-    ///
-    ///     let owning_ref_a: OwningRef<Box<[i32; 4]>, [i32; 4]>
-    ///         = OwningRef::new(Box::new([1, 2, 3, 4]));
-    ///
-    ///     let owning_ref_b: OwningRef<Box<Vec<(i32, bool)>>, Vec<(i32, bool)>>
-    ///         = OwningRef::new(Box::new(vec![(0, false), (1, true)]));
-    ///
-    ///     let owning_ref_a: OwningRef<Box<[i32; 4]>, i32>
-    ///         = owning_ref_a.map(|a| &a[0]);
-    ///
-    ///     let owning_ref_b: OwningRef<Box<Vec<(i32, bool)>>, i32>
-    ///         = owning_ref_b.map(|a| &a[1].0);
-    ///
-    ///     let owning_refs: [OwningRef<Box<dyn Erased>, i32>; 2]
-    ///         = [owning_ref_a.erase_owner(), owning_ref_b.erase_owner()];
-    ///
-    ///     assert_eq!(*owning_refs[0], 1);
-    ///     assert_eq!(*owning_refs[1], 1);
-    /// }
-    /// ```
-    pub fn erase_owner<'a>(self) -> OwningRef<O::Erased, T>
-    where
-        O: IntoErased<'a>,
-    {
-        OwningRef { reference: self.reference, owner: self.owner.into_erased() }
-    }
-
-    /// Erases the concrete base type of the owner with a trait object which implements `Send`.
-    ///
-    /// This allows mixing of owned references with different owner base types.
-    pub fn erase_send_owner<'a>(self) -> OwningRef<O::Erased, T>
-    where
-        O: IntoErasedSend<'a>,
-    {
-        OwningRef { reference: self.reference, owner: self.owner.into_erased_send() }
-    }
-
-    /// Erases the concrete base type of the owner with a trait object
-    /// which implements `Send` and `Sync`.
-    ///
-    /// This allows mixing of owned references with different owner base types.
-    pub fn erase_send_sync_owner<'a>(self) -> OwningRef<O::Erased, T>
-    where
-        O: IntoErasedSendSync<'a>,
-    {
-        OwningRef { reference: self.reference, owner: self.owner.into_erased_send_sync() }
-    }
-
-    // UNIMPLEMENTED: wrap_owner
-
-    // FIXME: Naming convention?
-    /// A getter for the underlying owner.
-    pub fn owner(&self) -> &O {
-        &self.owner
-    }
-
-    // FIXME: Naming convention?
-    /// Discards the reference and retrieves the owner.
-    pub fn into_inner(self) -> O {
-        self.owner
-    }
-}
-
-impl<O, T: ?Sized> OwningRefMut<O, T> {
-    /// Creates a new owning reference from an owner
-    /// initialized to the direct dereference of it.
-    ///
-    /// # Example
-    /// ```
-    /// use rustc_data_structures::owning_ref::OwningRefMut;
-    ///
-    /// fn main() {
-    ///     let owning_ref_mut = OwningRefMut::new(Box::new(42));
-    ///     assert_eq!(*owning_ref_mut, 42);
-    /// }
-    /// ```
-    pub fn new(mut o: O) -> Self
-    where
-        O: StableAddress,
-        O: DerefMut<Target = T>,
-    {
-        OwningRefMut { reference: &mut *o, owner: o }
-    }
-
-    /// Like `new`, but doesn’t require `O` to implement the `StableAddress` trait.
-    /// Instead, the caller is responsible to make the same promises as implementing the trait.
-    ///
-    /// This is useful for cases where coherence rules prevents implementing the trait
-    /// without adding a dependency to this crate in a third-party library.
-    pub unsafe fn new_assert_stable_address(mut o: O) -> Self
-    where
-        O: DerefMut<Target = T>,
-    {
-        OwningRefMut { reference: &mut *o, owner: o }
-    }
-
-    /// Converts `self` into a new _shared_ owning reference that points at
-    /// something reachable from the previous one.
-    ///
-    /// This can be a reference to a field of `U`, something reachable from a field of
-    /// `U`, or even something unrelated with a `'static` lifetime.
-    ///
-    /// # Example
-    /// ```
-    /// use rustc_data_structures::owning_ref::OwningRefMut;
-    ///
-    /// fn main() {
-    ///     let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4]));
-    ///
-    ///     // create an owning reference that points at the
-    ///     // third element of the array.
-    ///     let owning_ref = owning_ref_mut.map(|array| &array[2]);
-    ///     assert_eq!(*owning_ref, 3);
-    /// }
-    /// ```
-    pub fn map<F, U: ?Sized>(mut self, f: F) -> OwningRef<O, U>
-    where
-        O: StableAddress,
-        F: FnOnce(&mut T) -> &U,
-    {
-        OwningRef { reference: f(&mut self), owner: self.owner }
-    }
-
-    /// Converts `self` into a new _mutable_ owning reference that points at
-    /// something reachable from the previous one.
-    ///
-    /// This can be a reference to a field of `U`, something reachable from a field of
-    /// `U`, or even something unrelated with a `'static` lifetime.
-    ///
-    /// # Example
-    /// ```
-    /// use rustc_data_structures::owning_ref::OwningRefMut;
-    ///
-    /// fn main() {
-    ///     let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4]));
-    ///
-    ///     // create an owning reference that points at the
-    ///     // third element of the array.
-    ///     let owning_ref_mut = owning_ref_mut.map_mut(|array| &mut array[2]);
-    ///     assert_eq!(*owning_ref_mut, 3);
-    /// }
-    /// ```
-    pub fn map_mut<F, U: ?Sized>(mut self, f: F) -> OwningRefMut<O, U>
-    where
-        O: StableAddress,
-        F: FnOnce(&mut T) -> &mut U,
-    {
-        OwningRefMut { reference: f(&mut self), owner: self.owner }
-    }
-
-    /// Tries to convert `self` into a new _shared_ owning reference that points
-    /// at something reachable from the previous one.
-    ///
-    /// This can be a reference to a field of `U`, something reachable from a field of
-    /// `U`, or even something unrelated with a `'static` lifetime.
-    ///
-    /// # Example
-    /// ```
-    /// use rustc_data_structures::owning_ref::OwningRefMut;
-    ///
-    /// fn main() {
-    ///     let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4]));
-    ///
-    ///     // create an owning reference that points at the
-    ///     // third element of the array.
-    ///     let owning_ref = owning_ref_mut.try_map(|array| {
-    ///         if array[2] == 3 { Ok(&array[2]) } else { Err(()) }
-    ///     });
-    ///     assert_eq!(*owning_ref.unwrap(), 3);
-    /// }
-    /// ```
-    pub fn try_map<F, U: ?Sized, E>(mut self, f: F) -> Result<OwningRef<O, U>, E>
-    where
-        O: StableAddress,
-        F: FnOnce(&mut T) -> Result<&U, E>,
-    {
-        Ok(OwningRef { reference: f(&mut self)?, owner: self.owner })
-    }
-
-    /// Tries to convert `self` into a new _mutable_ owning reference that points
-    /// at something reachable from the previous one.
-    ///
-    /// This can be a reference to a field of `U`, something reachable from a field of
-    /// `U`, or even something unrelated with a `'static` lifetime.
-    ///
-    /// # Example
-    /// ```
-    /// use rustc_data_structures::owning_ref::OwningRefMut;
-    ///
-    /// fn main() {
-    ///     let owning_ref_mut = OwningRefMut::new(Box::new([1, 2, 3, 4]));
-    ///
-    ///     // create an owning reference that points at the
-    ///     // third element of the array.
-    ///     let owning_ref_mut = owning_ref_mut.try_map_mut(|array| {
-    ///         if array[2] == 3 { Ok(&mut array[2]) } else { Err(()) }
-    ///     });
-    ///     assert_eq!(*owning_ref_mut.unwrap(), 3);
-    /// }
-    /// ```
-    pub fn try_map_mut<F, U: ?Sized, E>(mut self, f: F) -> Result<OwningRefMut<O, U>, E>
-    where
-        O: StableAddress,
-        F: FnOnce(&mut T) -> Result<&mut U, E>,
-    {
-        Ok(OwningRefMut { reference: f(&mut self)?, owner: self.owner })
-    }
-
-    /// Converts `self` into a new owning reference with a different owner type.
-    ///
-    /// The new owner type needs to still contain the original owner in some way
-    /// so that the reference into it remains valid. This function is marked unsafe
-    /// because the user needs to manually uphold this guarantee.
-    pub unsafe fn map_owner<F, P>(self, f: F) -> OwningRefMut<P, T>
-    where
-        O: StableAddress,
-        P: StableAddress,
-        F: FnOnce(O) -> P,
-    {
-        OwningRefMut { reference: self.reference, owner: f(self.owner) }
-    }
-
-    /// Converts `self` into a new owning reference where the owner is wrapped
-    /// in an additional `Box<O>`.
-    ///
-    /// This can be used to safely erase the owner of any `OwningRefMut<O, T>`
-    /// to an `OwningRefMut<Box<Erased>, T>`.
-    pub fn map_owner_box(self) -> OwningRefMut<Box<O>, T> {
-        OwningRefMut { reference: self.reference, owner: Box::new(self.owner) }
-    }
-
-    /// Erases the concrete base type of the owner with a trait object.
-    ///
-    /// This allows mixing of owned references with different owner base types.
-    ///
-    /// # Example
-    /// ```
-    /// use rustc_data_structures::owning_ref::{OwningRefMut, Erased};
-    ///
-    /// fn main() {
-    ///     // N.B., using the concrete types here for explicitness.
-    ///     // For less verbose code type aliases like `BoxRef` are provided.
-    ///
-    ///     let owning_ref_mut_a: OwningRefMut<Box<[i32; 4]>, [i32; 4]>
-    ///         = OwningRefMut::new(Box::new([1, 2, 3, 4]));
-    ///
-    ///     let owning_ref_mut_b: OwningRefMut<Box<Vec<(i32, bool)>>, Vec<(i32, bool)>>
-    ///         = OwningRefMut::new(Box::new(vec![(0, false), (1, true)]));
-    ///
-    ///     let owning_ref_mut_a: OwningRefMut<Box<[i32; 4]>, i32>
-    ///         = owning_ref_mut_a.map_mut(|a| &mut a[0]);
-    ///
-    ///     let owning_ref_mut_b: OwningRefMut<Box<Vec<(i32, bool)>>, i32>
-    ///         = owning_ref_mut_b.map_mut(|a| &mut a[1].0);
-    ///
-    ///     let owning_refs_mut: [OwningRefMut<Box<dyn Erased>, i32>; 2]
-    ///         = [owning_ref_mut_a.erase_owner(), owning_ref_mut_b.erase_owner()];
-    ///
-    ///     assert_eq!(*owning_refs_mut[0], 1);
-    ///     assert_eq!(*owning_refs_mut[1], 1);
-    /// }
-    /// ```
-    pub fn erase_owner<'a>(self) -> OwningRefMut<O::Erased, T>
-    where
-        O: IntoErased<'a>,
-    {
-        OwningRefMut { reference: self.reference, owner: self.owner.into_erased() }
-    }
-
-    // UNIMPLEMENTED: wrap_owner
-
-    // FIXME: Naming convention?
-    /// A getter for the underlying owner.
-    pub fn owner(&self) -> &O {
-        &self.owner
-    }
-
-    // FIXME: Naming convention?
-    /// Discards the reference and retrieves the owner.
-    pub fn into_inner(self) -> O {
-        self.owner
-    }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// OwningHandle
-/////////////////////////////////////////////////////////////////////////////
-
-use std::ops::{Deref, DerefMut};
-
-/// `OwningHandle` is a complement to `OwningRef`. Where `OwningRef` allows
-/// consumers to pass around an owned object and a dependent reference,
-/// `OwningHandle` contains an owned object and a dependent _object_.
-///
-/// `OwningHandle` can encapsulate a `RefMut` along with its associated
-/// `RefCell`, or an `RwLockReadGuard` along with its associated `RwLock`.
-/// However, the API is completely generic and there are no restrictions on
-/// what types of owning and dependent objects may be used.
-///
-/// `OwningHandle` is created by passing an owner object (which dereferences
-/// to a stable address) along with a callback which receives a pointer to
-/// that stable location. The callback may then dereference the pointer and
-/// mint a dependent object, with the guarantee that the returned object will
-/// not outlive the referent of the pointer.
-///
-/// Since the callback needs to dereference a raw pointer, it requires `unsafe`
-/// code. To avoid forcing this unsafety on most callers, the `ToHandle` trait is
-/// implemented for common data structures. Types that implement `ToHandle` can
-/// be wrapped into an `OwningHandle` without passing a callback.
-pub struct OwningHandle<O, H>
-where
-    O: StableAddress,
-    H: Deref,
-{
-    handle: H,
-    _owner: O,
-}
-
-impl<O, H> Deref for OwningHandle<O, H>
-where
-    O: StableAddress,
-    H: Deref,
-{
-    type Target = H::Target;
-    fn deref(&self) -> &H::Target {
-        self.handle.deref()
-    }
-}
-
-unsafe impl<O, H> StableAddress for OwningHandle<O, H>
-where
-    O: StableAddress,
-    H: StableAddress,
-{
-}
-
-impl<O, H> DerefMut for OwningHandle<O, H>
-where
-    O: StableAddress,
-    H: DerefMut,
-{
-    fn deref_mut(&mut self) -> &mut H::Target {
-        self.handle.deref_mut()
-    }
-}
-
-/// Trait to implement the conversion of owner to handle for common types.
-pub trait ToHandle {
-    /// The type of handle to be encapsulated by the OwningHandle.
-    type Handle: Deref;
-
-    /// Given an appropriately-long-lived pointer to ourselves, create a
-    /// handle to be encapsulated by the `OwningHandle`.
-    unsafe fn to_handle(x: *const Self) -> Self::Handle;
-}
-
-/// Trait to implement the conversion of owner to mutable handle for common types.
-pub trait ToHandleMut {
-    /// The type of handle to be encapsulated by the OwningHandle.
-    type HandleMut: DerefMut;
-
-    /// Given an appropriately-long-lived pointer to ourselves, create a
-    /// mutable handle to be encapsulated by the `OwningHandle`.
-    unsafe fn to_handle_mut(x: *const Self) -> Self::HandleMut;
-}
-
-impl<O, H> OwningHandle<O, H>
-where
-    O: StableAddress<Target: ToHandle<Handle = H>>,
-    H: Deref,
-{
-    /// Creates a new `OwningHandle` for a type that implements `ToHandle`. For types
-    /// that don't implement `ToHandle`, callers may invoke `new_with_fn`, which accepts
-    /// a callback to perform the conversion.
-    pub fn new(o: O) -> Self {
-        OwningHandle::new_with_fn(o, |x| unsafe { O::Target::to_handle(x) })
-    }
-}
-
-impl<O, H> OwningHandle<O, H>
-where
-    O: StableAddress<Target: ToHandleMut<HandleMut = H>>,
-    H: DerefMut,
-{
-    /// Creates a new mutable `OwningHandle` for a type that implements `ToHandleMut`.
-    pub fn new_mut(o: O) -> Self {
-        OwningHandle::new_with_fn(o, |x| unsafe { O::Target::to_handle_mut(x) })
-    }
-}
-
-impl<O, H> OwningHandle<O, H>
-where
-    O: StableAddress,
-    H: Deref,
-{
-    /// Creates a new OwningHandle. The provided callback will be invoked with
-    /// a pointer to the object owned by `o`, and the returned value is stored
-    /// as the object to which this `OwningHandle` will forward `Deref` and
-    /// `DerefMut`.
-    pub fn new_with_fn<F>(o: O, f: F) -> Self
-    where
-        F: FnOnce(*const O::Target) -> H,
-    {
-        let h: H;
-        {
-            h = f(o.deref() as *const O::Target);
-        }
-
-        OwningHandle { handle: h, _owner: o }
-    }
-
-    /// Creates a new OwningHandle. The provided callback will be invoked with
-    /// a pointer to the object owned by `o`, and the returned value is stored
-    /// as the object to which this `OwningHandle` will forward `Deref` and
-    /// `DerefMut`.
-    pub fn try_new<F, E>(o: O, f: F) -> Result<Self, E>
-    where
-        F: FnOnce(*const O::Target) -> Result<H, E>,
-    {
-        let h: H;
-        {
-            h = f(o.deref() as *const O::Target)?;
-        }
-
-        Ok(OwningHandle { handle: h, _owner: o })
-    }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// std traits
-/////////////////////////////////////////////////////////////////////////////
-
-use std::borrow::Borrow;
-use std::cmp::Ordering;
-use std::fmt::{self, Debug};
-use std::hash::{Hash, Hasher};
-
-impl<O, T: ?Sized> Deref for OwningRef<O, T> {
-    type Target = T;
-
-    fn deref(&self) -> &T {
-        unsafe { &*self.reference }
-    }
-}
-
-impl<O, T: ?Sized> Deref for OwningRefMut<O, T> {
-    type Target = T;
-
-    fn deref(&self) -> &T {
-        unsafe { &*self.reference }
-    }
-}
-
-impl<O, T: ?Sized> DerefMut for OwningRefMut<O, T> {
-    fn deref_mut(&mut self) -> &mut T {
-        unsafe { &mut *self.reference }
-    }
-}
-
-unsafe impl<O, T: ?Sized> StableAddress for OwningRef<O, T> {}
-
-impl<O, T: ?Sized> AsRef<T> for OwningRef<O, T> {
-    fn as_ref(&self) -> &T {
-        self
-    }
-}
-
-impl<O, T: ?Sized> AsRef<T> for OwningRefMut<O, T> {
-    fn as_ref(&self) -> &T {
-        self
-    }
-}
-
-impl<O, T: ?Sized> AsMut<T> for OwningRefMut<O, T> {
-    fn as_mut(&mut self) -> &mut T {
-        self
-    }
-}
-
-impl<O, T: ?Sized> Borrow<T> for OwningRef<O, T> {
-    fn borrow(&self) -> &T {
-        self
-    }
-}
-
-impl<O, T: ?Sized> From<O> for OwningRef<O, T>
-where
-    O: StableAddress,
-    O: Deref<Target = T>,
-{
-    fn from(owner: O) -> Self {
-        OwningRef::new(owner)
-    }
-}
-
-impl<O, T: ?Sized> From<O> for OwningRefMut<O, T>
-where
-    O: StableAddress,
-    O: DerefMut<Target = T>,
-{
-    fn from(owner: O) -> Self {
-        OwningRefMut::new(owner)
-    }
-}
-
-impl<O, T: ?Sized> From<OwningRefMut<O, T>> for OwningRef<O, T>
-where
-    O: StableAddress,
-    O: DerefMut<Target = T>,
-{
-    fn from(other: OwningRefMut<O, T>) -> Self {
-        OwningRef { owner: other.owner, reference: other.reference }
-    }
-}
-
-// ^ FIXME: Is an Into impl for calling into_inner() possible as well?
-
-impl<O, T: ?Sized> Debug for OwningRef<O, T>
-where
-    O: Debug,
-    T: Debug,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "OwningRef {{ owner: {:?}, reference: {:?} }}", self.owner(), &**self)
-    }
-}
-
-impl<O, T: ?Sized> Debug for OwningRefMut<O, T>
-where
-    O: Debug,
-    T: Debug,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "OwningRefMut {{ owner: {:?}, reference: {:?} }}", self.owner(), &**self)
-    }
-}
-
-impl<O, T: ?Sized> Clone for OwningRef<O, T>
-where
-    O: CloneStableAddress,
-{
-    fn clone(&self) -> Self {
-        OwningRef { owner: self.owner.clone(), reference: self.reference }
-    }
-}
-
-unsafe impl<O, T: ?Sized> CloneStableAddress for OwningRef<O, T> where O: CloneStableAddress {}
-
-unsafe impl<O, T: ?Sized> Send for OwningRef<O, T>
-where
-    O: Send,
-    for<'a> &'a T: Send,
-{
-}
-unsafe impl<O, T: ?Sized> Sync for OwningRef<O, T>
-where
-    O: Sync,
-    for<'a> &'a T: Sync,
-{
-}
-
-unsafe impl<O, T: ?Sized> Send for OwningRefMut<O, T>
-where
-    O: Send,
-    for<'a> &'a mut T: Send,
-{
-}
-unsafe impl<O, T: ?Sized> Sync for OwningRefMut<O, T>
-where
-    O: Sync,
-    for<'a> &'a mut T: Sync,
-{
-}
-
-impl Debug for dyn Erased {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "<Erased>",)
-    }
-}
-
-impl<O, T: ?Sized> PartialEq for OwningRef<O, T>
-where
-    T: PartialEq,
-{
-    fn eq(&self, other: &Self) -> bool {
-        self.deref().eq(other.deref())
-    }
-}
-
-impl<O, T: ?Sized> Eq for OwningRef<O, T> where T: Eq {}
-
-impl<O, T: ?Sized> PartialOrd for OwningRef<O, T>
-where
-    T: PartialOrd,
-{
-    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-        self.deref().partial_cmp(other.deref())
-    }
-}
-
-impl<O, T: ?Sized> Ord for OwningRef<O, T>
-where
-    T: Ord,
-{
-    fn cmp(&self, other: &Self) -> Ordering {
-        self.deref().cmp(other.deref())
-    }
-}
-
-impl<O, T: ?Sized> Hash for OwningRef<O, T>
-where
-    T: Hash,
-{
-    fn hash<H: Hasher>(&self, state: &mut H) {
-        self.deref().hash(state);
-    }
-}
-
-impl<O, T: ?Sized> PartialEq for OwningRefMut<O, T>
-where
-    T: PartialEq,
-{
-    fn eq(&self, other: &Self) -> bool {
-        self.deref().eq(other.deref())
-    }
-}
-
-impl<O, T: ?Sized> Eq for OwningRefMut<O, T> where T: Eq {}
-
-impl<O, T: ?Sized> PartialOrd for OwningRefMut<O, T>
-where
-    T: PartialOrd,
-{
-    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-        self.deref().partial_cmp(other.deref())
-    }
-}
-
-impl<O, T: ?Sized> Ord for OwningRefMut<O, T>
-where
-    T: Ord,
-{
-    fn cmp(&self, other: &Self) -> Ordering {
-        self.deref().cmp(other.deref())
-    }
-}
-
-impl<O, T: ?Sized> Hash for OwningRefMut<O, T>
-where
-    T: Hash,
-{
-    fn hash<H: Hasher>(&self, state: &mut H) {
-        self.deref().hash(state);
-    }
-}
-
-/////////////////////////////////////////////////////////////////////////////
-// std types integration and convenience type defs
-/////////////////////////////////////////////////////////////////////////////
-
-use std::cell::{Ref, RefCell, RefMut};
-use std::rc::Rc;
-use std::sync::Arc;
-use std::sync::{MutexGuard, RwLockReadGuard, RwLockWriteGuard};
-
-impl<T: 'static> ToHandle for RefCell<T> {
-    type Handle = Ref<'static, T>;
-    unsafe fn to_handle(x: *const Self) -> Self::Handle {
-        (*x).borrow()
-    }
-}
-
-impl<T: 'static> ToHandleMut for RefCell<T> {
-    type HandleMut = RefMut<'static, T>;
-    unsafe fn to_handle_mut(x: *const Self) -> Self::HandleMut {
-        (*x).borrow_mut()
-    }
-}
-
-// N.B., implementing ToHandle{,Mut} for Mutex and RwLock requires a decision
-// about which handle creation to use (i.e., read() vs try_read()) as well as
-// what to do with error results.
-
-/// Typedef of an owning reference that uses a `Box` as the owner.
-pub type BoxRef<T, U = T> = OwningRef<Box<T>, U>;
-/// Typedef of an owning reference that uses a `Vec` as the owner.
-pub type VecRef<T, U = T> = OwningRef<Vec<T>, U>;
-/// Typedef of an owning reference that uses a `String` as the owner.
-pub type StringRef = OwningRef<String, str>;
-
-/// Typedef of an owning reference that uses an `Rc` as the owner.
-pub type RcRef<T, U = T> = OwningRef<Rc<T>, U>;
-/// Typedef of an owning reference that uses an `Arc` as the owner.
-pub type ArcRef<T, U = T> = OwningRef<Arc<T>, U>;
-
-/// Typedef of an owning reference that uses a `Ref` as the owner.
-pub type RefRef<'a, T, U = T> = OwningRef<Ref<'a, T>, U>;
-/// Typedef of an owning reference that uses a `RefMut` as the owner.
-pub type RefMutRef<'a, T, U = T> = OwningRef<RefMut<'a, T>, U>;
-/// Typedef of an owning reference that uses a `MutexGuard` as the owner.
-pub type MutexGuardRef<'a, T, U = T> = OwningRef<MutexGuard<'a, T>, U>;
-/// Typedef of an owning reference that uses an `RwLockReadGuard` as the owner.
-pub type RwLockReadGuardRef<'a, T, U = T> = OwningRef<RwLockReadGuard<'a, T>, U>;
-/// Typedef of an owning reference that uses an `RwLockWriteGuard` as the owner.
-pub type RwLockWriteGuardRef<'a, T, U = T> = OwningRef<RwLockWriteGuard<'a, T>, U>;
-
-/// Typedef of a mutable owning reference that uses a `Box` as the owner.
-pub type BoxRefMut<T, U = T> = OwningRefMut<Box<T>, U>;
-/// Typedef of a mutable owning reference that uses a `Vec` as the owner.
-pub type VecRefMut<T, U = T> = OwningRefMut<Vec<T>, U>;
-/// Typedef of a mutable owning reference that uses a `String` as the owner.
-pub type StringRefMut = OwningRefMut<String, str>;
-
-/// Typedef of a mutable owning reference that uses a `RefMut` as the owner.
-pub type RefMutRefMut<'a, T, U = T> = OwningRefMut<RefMut<'a, T>, U>;
-/// Typedef of a mutable owning reference that uses a `MutexGuard` as the owner.
-pub type MutexGuardRefMut<'a, T, U = T> = OwningRefMut<MutexGuard<'a, T>, U>;
-/// Typedef of a mutable owning reference that uses an `RwLockWriteGuard` as the owner.
-pub type RwLockWriteGuardRefMut<'a, T, U = T> = OwningRef<RwLockWriteGuard<'a, T>, U>;
-
-unsafe impl<'a, T: 'a> IntoErased<'a> for Box<T> {
-    type Erased = Box<dyn Erased + 'a>;
-    fn into_erased(self) -> Self::Erased {
-        self
-    }
-}
-unsafe impl<'a, T: 'a> IntoErased<'a> for Rc<T> {
-    type Erased = Rc<dyn Erased + 'a>;
-    fn into_erased(self) -> Self::Erased {
-        self
-    }
-}
-unsafe impl<'a, T: 'a> IntoErased<'a> for Arc<T> {
-    type Erased = Arc<dyn Erased + 'a>;
-    fn into_erased(self) -> Self::Erased {
-        self
-    }
-}
-
-unsafe impl<'a, T: Send + 'a> IntoErasedSend<'a> for Box<T> {
-    type Erased = Box<dyn Erased + Send + 'a>;
-    fn into_erased_send(self) -> Self::Erased {
-        self
-    }
-}
-
-unsafe impl<'a, T: Send + 'a> IntoErasedSendSync<'a> for Box<T> {
-    type Erased = Box<dyn Erased + Sync + Send + 'a>;
-    fn into_erased_send_sync(self) -> Self::Erased {
-        let result: Box<dyn Erased + Send + 'a> = self;
-        // This is safe since Erased can always implement Sync
-        // Only the destructor is available and it takes &mut self
-        unsafe { mem::transmute(result) }
-    }
-}
-
-unsafe impl<'a, T: Send + Sync + 'a> IntoErasedSendSync<'a> for Arc<T> {
-    type Erased = Arc<dyn Erased + Send + Sync + 'a>;
-    fn into_erased_send_sync(self) -> Self::Erased {
-        self
-    }
-}
-
-/// Typedef of an owning reference that uses an erased `Box` as the owner.
-pub type ErasedBoxRef<U> = OwningRef<Box<dyn Erased>, U>;
-/// Typedef of an owning reference that uses an erased `Rc` as the owner.
-pub type ErasedRcRef<U> = OwningRef<Rc<dyn Erased>, U>;
-/// Typedef of an owning reference that uses an erased `Arc` as the owner.
-pub type ErasedArcRef<U> = OwningRef<Arc<dyn Erased>, U>;
-
-/// Typedef of a mutable owning reference that uses an erased `Box` as the owner.
-pub type ErasedBoxRefMut<U> = OwningRefMut<Box<dyn Erased>, U>;
-
-#[cfg(test)]
-mod tests;
diff --git a/compiler/rustc_data_structures/src/owning_ref/tests.rs b/compiler/rustc_data_structures/src/owning_ref/tests.rs
deleted file mode 100644
index a9b187c4ce0..00000000000
--- a/compiler/rustc_data_structures/src/owning_ref/tests.rs
+++ /dev/null
@@ -1,711 +0,0 @@
-// FIXME: owning_ref is not sound under stacked borrows. Preferably, get rid of it.
-#[cfg(not(miri))]
-mod owning_ref {
-    use super::super::OwningRef;
-    use super::super::{BoxRef, Erased, ErasedBoxRef, RcRef};
-    use std::cmp::Ordering;
-    use std::collections::hash_map::DefaultHasher;
-    use std::collections::HashMap;
-    use std::hash::{Hash, Hasher};
-    use std::rc::Rc;
-
-    #[derive(Debug, PartialEq)]
-    struct Example(u32, String, [u8; 3]);
-    fn example() -> Example {
-        Example(42, "hello world".to_string(), [1, 2, 3])
-    }
-
-    #[test]
-    fn new_deref() {
-        let or: OwningRef<Box<()>, ()> = OwningRef::new(Box::new(()));
-        assert_eq!(&*or, &());
-    }
-
-    #[test]
-    fn into() {
-        let or: OwningRef<Box<()>, ()> = Box::new(()).into();
-        assert_eq!(&*or, &());
-    }
-
-    #[test]
-    fn map_offset_ref() {
-        let or: BoxRef<Example> = Box::new(example()).into();
-        let or: BoxRef<_, u32> = or.map(|x| &x.0);
-        assert_eq!(&*or, &42);
-
-        let or: BoxRef<Example> = Box::new(example()).into();
-        let or: BoxRef<_, u8> = or.map(|x| &x.2[1]);
-        assert_eq!(&*or, &2);
-    }
-
-    #[test]
-    fn map_heap_ref() {
-        let or: BoxRef<Example> = Box::new(example()).into();
-        let or: BoxRef<_, str> = or.map(|x| &x.1[..5]);
-        assert_eq!(&*or, "hello");
-    }
-
-    #[test]
-    fn map_static_ref() {
-        let or: BoxRef<()> = Box::new(()).into();
-        let or: BoxRef<_, str> = or.map(|_| "hello");
-        assert_eq!(&*or, "hello");
-    }
-
-    #[test]
-    fn map_chained() {
-        let or: BoxRef<String> = Box::new(example().1).into();
-        let or: BoxRef<_, str> = or.map(|x| &x[1..5]);
-        let or: BoxRef<_, str> = or.map(|x| &x[..2]);
-        assert_eq!(&*or, "el");
-    }
-
-    #[test]
-    fn map_chained_inference() {
-        let or = BoxRef::new(Box::new(example().1)).map(|x| &x[..5]).map(|x| &x[1..3]);
-        assert_eq!(&*or, "el");
-    }
-
-    #[test]
-    fn owner() {
-        let or: BoxRef<String> = Box::new(example().1).into();
-        let or = or.map(|x| &x[..5]);
-        assert_eq!(&*or, "hello");
-        assert_eq!(&**or.owner(), "hello world");
-    }
-
-    #[test]
-    fn into_inner() {
-        let or: BoxRef<String> = Box::new(example().1).into();
-        let or = or.map(|x| &x[..5]);
-        assert_eq!(&*or, "hello");
-        let s = *or.into_inner();
-        assert_eq!(&s, "hello world");
-    }
-
-    #[test]
-    fn fmt_debug() {
-        let or: BoxRef<String> = Box::new(example().1).into();
-        let or = or.map(|x| &x[..5]);
-        let s = format!("{:?}", or);
-        assert_eq!(&s, "OwningRef { owner: \"hello world\", reference: \"hello\" }");
-    }
-
-    #[test]
-    fn erased_owner() {
-        let o1: BoxRef<Example, str> = BoxRef::new(Box::new(example())).map(|x| &x.1[..]);
-
-        let o2: BoxRef<String, str> = BoxRef::new(Box::new(example().1)).map(|x| &x[..]);
-
-        let os: Vec<ErasedBoxRef<str>> = vec![o1.erase_owner(), o2.erase_owner()];
-        assert!(os.iter().all(|e| &e[..] == "hello world"));
-    }
-
-    #[test]
-    fn raii_locks() {
-        use super::super::{MutexGuardRef, RwLockReadGuardRef, RwLockWriteGuardRef};
-        use super::super::{RefMutRef, RefRef};
-        use std::cell::RefCell;
-        use std::sync::{Mutex, RwLock};
-
-        {
-            let a = RefCell::new(1);
-            let a = {
-                let a = RefRef::new(a.borrow());
-                assert_eq!(*a, 1);
-                a
-            };
-            assert_eq!(*a, 1);
-            drop(a);
-        }
-        {
-            let a = RefCell::new(1);
-            let a = {
-                let a = RefMutRef::new(a.borrow_mut());
-                assert_eq!(*a, 1);
-                a
-            };
-            assert_eq!(*a, 1);
-            drop(a);
-        }
-        {
-            let a = Mutex::new(1);
-            let a = {
-                let a = MutexGuardRef::new(a.lock().unwrap());
-                assert_eq!(*a, 1);
-                a
-            };
-            assert_eq!(*a, 1);
-            drop(a);
-        }
-        {
-            let a = RwLock::new(1);
-            let a = {
-                let a = RwLockReadGuardRef::new(a.read().unwrap());
-                assert_eq!(*a, 1);
-                a
-            };
-            assert_eq!(*a, 1);
-            drop(a);
-        }
-        {
-            let a = RwLock::new(1);
-            let a = {
-                let a = RwLockWriteGuardRef::new(a.write().unwrap());
-                assert_eq!(*a, 1);
-                a
-            };
-            assert_eq!(*a, 1);
-            drop(a);
-        }
-    }
-
-    #[test]
-    fn eq() {
-        let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice());
-        let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice());
-        assert_eq!(or1.eq(&or2), true);
-    }
-
-    #[test]
-    fn cmp() {
-        let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice());
-        let or2: BoxRef<[u8]> = BoxRef::new(vec![4, 5, 6].into_boxed_slice());
-        assert_eq!(or1.cmp(&or2), Ordering::Less);
-    }
-
-    #[test]
-    fn partial_cmp() {
-        let or1: BoxRef<[u8]> = BoxRef::new(vec![4, 5, 6].into_boxed_slice());
-        let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice());
-        assert_eq!(or1.partial_cmp(&or2), Some(Ordering::Greater));
-    }
-
-    #[test]
-    fn hash() {
-        let mut h1 = DefaultHasher::new();
-        let mut h2 = DefaultHasher::new();
-
-        let or1: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice());
-        let or2: BoxRef<[u8]> = BoxRef::new(vec![1, 2, 3].into_boxed_slice());
-
-        or1.hash(&mut h1);
-        or2.hash(&mut h2);
-
-        assert_eq!(h1.finish(), h2.finish());
-    }
-
-    #[test]
-    fn borrow() {
-        let mut hash = HashMap::new();
-        let key = RcRef::<String>::new(Rc::new("foo-bar".to_string())).map(|s| &s[..]);
-
-        hash.insert(key.clone().map(|s| &s[..3]), 42);
-        hash.insert(key.clone().map(|s| &s[4..]), 23);
-
-        assert_eq!(hash.get("foo"), Some(&42));
-        assert_eq!(hash.get("bar"), Some(&23));
-    }
-
-    #[test]
-    fn total_erase() {
-        let a: OwningRef<Vec<u8>, [u8]> = OwningRef::new(vec![]).map(|x| &x[..]);
-        let b: OwningRef<Box<[u8]>, [u8]> =
-            OwningRef::new(vec![].into_boxed_slice()).map(|x| &x[..]);
-
-        let c: OwningRef<Rc<Vec<u8>>, [u8]> = unsafe { a.map_owner(Rc::new) };
-        let d: OwningRef<Rc<Box<[u8]>>, [u8]> = unsafe { b.map_owner(Rc::new) };
-
-        let e: OwningRef<Rc<dyn Erased>, [u8]> = c.erase_owner();
-        let f: OwningRef<Rc<dyn Erased>, [u8]> = d.erase_owner();
-
-        let _g = e.clone();
-        let _h = f.clone();
-    }
-
-    #[test]
-    fn total_erase_box() {
-        let a: OwningRef<Vec<u8>, [u8]> = OwningRef::new(vec![]).map(|x| &x[..]);
-        let b: OwningRef<Box<[u8]>, [u8]> =
-            OwningRef::new(vec![].into_boxed_slice()).map(|x| &x[..]);
-
-        let c: OwningRef<Box<Vec<u8>>, [u8]> = a.map_owner_box();
-        let d: OwningRef<Box<Box<[u8]>>, [u8]> = b.map_owner_box();
-
-        let _e: OwningRef<Box<dyn Erased>, [u8]> = c.erase_owner();
-        let _f: OwningRef<Box<dyn Erased>, [u8]> = d.erase_owner();
-    }
-
-    #[test]
-    fn try_map1() {
-        use std::any::Any;
-
-        let x = Box::new(123_i32);
-        let y: Box<dyn Any> = x;
-
-        assert!(OwningRef::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).is_ok());
-    }
-
-    #[test]
-    fn try_map2() {
-        use std::any::Any;
-
-        let x = Box::new(123_i32);
-        let y: Box<dyn Any> = x;
-
-        assert!(!OwningRef::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).is_err());
-    }
-}
-
-mod owning_handle {
-    use super::super::OwningHandle;
-    use super::super::RcRef;
-    use std::cell::RefCell;
-    use std::rc::Rc;
-    use std::sync::Arc;
-    use std::sync::RwLock;
-
-    #[test]
-    fn owning_handle() {
-        use std::cell::RefCell;
-        let cell = Rc::new(RefCell::new(2));
-        let cell_ref = RcRef::new(cell);
-        let mut handle =
-            OwningHandle::new_with_fn(cell_ref, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
-        assert_eq!(*handle, 2);
-        *handle = 3;
-        assert_eq!(*handle, 3);
-    }
-
-    #[test]
-    fn try_owning_handle_ok() {
-        use std::cell::RefCell;
-        let cell = Rc::new(RefCell::new(2));
-        let cell_ref = RcRef::new(cell);
-        let mut handle = OwningHandle::try_new::<_, ()>(cell_ref, |x| {
-            Ok(unsafe { x.as_ref() }.unwrap().borrow_mut())
-        })
-        .unwrap();
-        assert_eq!(*handle, 2);
-        *handle = 3;
-        assert_eq!(*handle, 3);
-    }
-
-    #[test]
-    fn try_owning_handle_err() {
-        use std::cell::RefCell;
-        let cell = Rc::new(RefCell::new(2));
-        let cell_ref = RcRef::new(cell);
-        let handle = OwningHandle::try_new::<_, ()>(cell_ref, |x| {
-            if false {
-                return Ok(unsafe { x.as_ref() }.unwrap().borrow_mut());
-            }
-            Err(())
-        });
-        assert!(handle.is_err());
-    }
-
-    #[test]
-    fn nested() {
-        use std::cell::RefCell;
-        use std::sync::{Arc, RwLock};
-
-        let result = {
-            let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString"))));
-            let curr = RcRef::new(complex);
-            let curr =
-                OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
-            let mut curr = OwningHandle::new_with_fn(curr, |x| {
-                unsafe { x.as_ref() }.unwrap().try_write().unwrap()
-            });
-            assert_eq!(*curr, "someString");
-            *curr = "someOtherString";
-            curr
-        };
-        assert_eq!(*result, "someOtherString");
-    }
-
-    #[test]
-    fn owning_handle_safe() {
-        use std::cell::RefCell;
-        let cell = Rc::new(RefCell::new(2));
-        let cell_ref = RcRef::new(cell);
-        let handle = OwningHandle::new(cell_ref);
-        assert_eq!(*handle, 2);
-    }
-
-    #[test]
-    fn owning_handle_mut_safe() {
-        use std::cell::RefCell;
-        let cell = Rc::new(RefCell::new(2));
-        let cell_ref = RcRef::new(cell);
-        let mut handle = OwningHandle::new_mut(cell_ref);
-        assert_eq!(*handle, 2);
-        *handle = 3;
-        assert_eq!(*handle, 3);
-    }
-
-    #[test]
-    fn owning_handle_safe_2() {
-        let result = {
-            let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString"))));
-            let curr = RcRef::new(complex);
-            let curr =
-                OwningHandle::new_with_fn(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
-            let mut curr = OwningHandle::new_with_fn(curr, |x| {
-                unsafe { x.as_ref() }.unwrap().try_write().unwrap()
-            });
-            assert_eq!(*curr, "someString");
-            *curr = "someOtherString";
-            curr
-        };
-        assert_eq!(*result, "someOtherString");
-    }
-}
-
-// FIXME: owning_ref is not sound under stacked borrows. Preferably, get rid of it.
-#[cfg(not(miri))]
-mod owning_ref_mut {
-    use super::super::BoxRef;
-    use super::super::{BoxRefMut, Erased, ErasedBoxRefMut, OwningRefMut};
-    use std::cmp::Ordering;
-    use std::collections::hash_map::DefaultHasher;
-    use std::collections::HashMap;
-    use std::hash::{Hash, Hasher};
-
-    #[derive(Debug, PartialEq)]
-    struct Example(u32, String, [u8; 3]);
-    fn example() -> Example {
-        Example(42, "hello world".to_string(), [1, 2, 3])
-    }
-
-    #[test]
-    fn new_deref() {
-        let or: OwningRefMut<Box<()>, ()> = OwningRefMut::new(Box::new(()));
-        assert_eq!(&*or, &());
-    }
-
-    #[test]
-    fn new_deref_mut() {
-        let mut or: OwningRefMut<Box<()>, ()> = OwningRefMut::new(Box::new(()));
-        assert_eq!(&mut *or, &mut ());
-    }
-
-    #[test]
-    fn mutate() {
-        let mut or: OwningRefMut<Box<usize>, usize> = OwningRefMut::new(Box::new(0));
-        assert_eq!(&*or, &0);
-        *or = 1;
-        assert_eq!(&*or, &1);
-    }
-
-    #[test]
-    fn into() {
-        let or: OwningRefMut<Box<()>, ()> = Box::new(()).into();
-        assert_eq!(&*or, &());
-    }
-
-    #[test]
-    fn map_offset_ref() {
-        let or: BoxRefMut<Example> = Box::new(example()).into();
-        let or: BoxRef<_, u32> = or.map(|x| &mut x.0);
-        assert_eq!(&*or, &42);
-
-        let or: BoxRefMut<Example> = Box::new(example()).into();
-        let or: BoxRef<_, u8> = or.map(|x| &mut x.2[1]);
-        assert_eq!(&*or, &2);
-    }
-
-    #[test]
-    fn map_heap_ref() {
-        let or: BoxRefMut<Example> = Box::new(example()).into();
-        let or: BoxRef<_, str> = or.map(|x| &mut x.1[..5]);
-        assert_eq!(&*or, "hello");
-    }
-
-    #[test]
-    fn map_static_ref() {
-        let or: BoxRefMut<()> = Box::new(()).into();
-        let or: BoxRef<_, str> = or.map(|_| "hello");
-        assert_eq!(&*or, "hello");
-    }
-
-    #[test]
-    fn map_mut_offset_ref() {
-        let or: BoxRefMut<Example> = Box::new(example()).into();
-        let or: BoxRefMut<_, u32> = or.map_mut(|x| &mut x.0);
-        assert_eq!(&*or, &42);
-
-        let or: BoxRefMut<Example> = Box::new(example()).into();
-        let or: BoxRefMut<_, u8> = or.map_mut(|x| &mut x.2[1]);
-        assert_eq!(&*or, &2);
-    }
-
-    #[test]
-    fn map_mut_heap_ref() {
-        let or: BoxRefMut<Example> = Box::new(example()).into();
-        let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x.1[..5]);
-        assert_eq!(&*or, "hello");
-    }
-
-    #[test]
-    fn map_mut_static_ref() {
-        static mut MUT_S: [u8; 5] = *b"hello";
-
-        let mut_s: &'static mut [u8] = unsafe { &mut MUT_S };
-
-        let or: BoxRefMut<()> = Box::new(()).into();
-        let or: BoxRefMut<_, [u8]> = or.map_mut(move |_| mut_s);
-        assert_eq!(&*or, b"hello");
-    }
-
-    #[test]
-    fn map_mut_chained() {
-        let or: BoxRefMut<String> = Box::new(example().1).into();
-        let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x[1..5]);
-        let or: BoxRefMut<_, str> = or.map_mut(|x| &mut x[..2]);
-        assert_eq!(&*or, "el");
-    }
-
-    #[test]
-    fn map_chained_inference() {
-        let or = BoxRefMut::new(Box::new(example().1))
-            .map_mut(|x| &mut x[..5])
-            .map_mut(|x| &mut x[1..3]);
-        assert_eq!(&*or, "el");
-    }
-
-    #[test]
-    fn try_map_mut() {
-        let or: BoxRefMut<String> = Box::new(example().1).into();
-        let or: Result<BoxRefMut<_, str>, ()> = or.try_map_mut(|x| Ok(&mut x[1..5]));
-        assert_eq!(&*or.unwrap(), "ello");
-
-        let or: BoxRefMut<String> = Box::new(example().1).into();
-        let or: Result<BoxRefMut<_, str>, ()> = or.try_map_mut(|_| Err(()));
-        assert!(or.is_err());
-    }
-
-    #[test]
-    fn owner() {
-        let or: BoxRefMut<String> = Box::new(example().1).into();
-        let or = or.map_mut(|x| &mut x[..5]);
-        assert_eq!(&*or, "hello");
-        assert_eq!(&**or.owner(), "hello world");
-    }
-
-    #[test]
-    fn into_inner() {
-        let or: BoxRefMut<String> = Box::new(example().1).into();
-        let or = or.map_mut(|x| &mut x[..5]);
-        assert_eq!(&*or, "hello");
-        let s = *or.into_inner();
-        assert_eq!(&s, "hello world");
-    }
-
-    #[test]
-    fn fmt_debug() {
-        let or: BoxRefMut<String> = Box::new(example().1).into();
-        let or = or.map_mut(|x| &mut x[..5]);
-        let s = format!("{:?}", or);
-        assert_eq!(&s, "OwningRefMut { owner: \"hello world\", reference: \"hello\" }");
-    }
-
-    #[test]
-    fn erased_owner() {
-        let o1: BoxRefMut<Example, str> =
-            BoxRefMut::new(Box::new(example())).map_mut(|x| &mut x.1[..]);
-
-        let o2: BoxRefMut<String, str> =
-            BoxRefMut::new(Box::new(example().1)).map_mut(|x| &mut x[..]);
-
-        let os: Vec<ErasedBoxRefMut<str>> = vec![o1.erase_owner(), o2.erase_owner()];
-        assert!(os.iter().all(|e| &e[..] == "hello world"));
-    }
-
-    #[test]
-    fn raii_locks() {
-        use super::super::RefMutRefMut;
-        use super::super::{MutexGuardRefMut, RwLockWriteGuardRefMut};
-        use std::cell::RefCell;
-        use std::sync::{Mutex, RwLock};
-
-        {
-            let a = RefCell::new(1);
-            let a = {
-                let a = RefMutRefMut::new(a.borrow_mut());
-                assert_eq!(*a, 1);
-                a
-            };
-            assert_eq!(*a, 1);
-            drop(a);
-        }
-        {
-            let a = Mutex::new(1);
-            let a = {
-                let a = MutexGuardRefMut::new(a.lock().unwrap());
-                assert_eq!(*a, 1);
-                a
-            };
-            assert_eq!(*a, 1);
-            drop(a);
-        }
-        {
-            let a = RwLock::new(1);
-            let a = {
-                let a = RwLockWriteGuardRefMut::new(a.write().unwrap());
-                assert_eq!(*a, 1);
-                a
-            };
-            assert_eq!(*a, 1);
-            drop(a);
-        }
-    }
-
-    #[test]
-    fn eq() {
-        let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice());
-        let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice());
-        assert_eq!(or1.eq(&or2), true);
-    }
-
-    #[test]
-    fn cmp() {
-        let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice());
-        let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![4, 5, 6].into_boxed_slice());
-        assert_eq!(or1.cmp(&or2), Ordering::Less);
-    }
-
-    #[test]
-    fn partial_cmp() {
-        let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![4, 5, 6].into_boxed_slice());
-        let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice());
-        assert_eq!(or1.partial_cmp(&or2), Some(Ordering::Greater));
-    }
-
-    #[test]
-    fn hash() {
-        let mut h1 = DefaultHasher::new();
-        let mut h2 = DefaultHasher::new();
-
-        let or1: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice());
-        let or2: BoxRefMut<[u8]> = BoxRefMut::new(vec![1, 2, 3].into_boxed_slice());
-
-        or1.hash(&mut h1);
-        or2.hash(&mut h2);
-
-        assert_eq!(h1.finish(), h2.finish());
-    }
-
-    #[test]
-    fn borrow() {
-        let mut hash = HashMap::new();
-        let key1 = BoxRefMut::<String>::new(Box::new("foo".to_string())).map(|s| &s[..]);
-        let key2 = BoxRefMut::<String>::new(Box::new("bar".to_string())).map(|s| &s[..]);
-
-        hash.insert(key1, 42);
-        hash.insert(key2, 23);
-
-        assert_eq!(hash.get("foo"), Some(&42));
-        assert_eq!(hash.get("bar"), Some(&23));
-    }
-
-    #[test]
-    fn total_erase() {
-        let a: OwningRefMut<Vec<u8>, [u8]> = OwningRefMut::new(vec![]).map_mut(|x| &mut x[..]);
-        let b: OwningRefMut<Box<[u8]>, [u8]> =
-            OwningRefMut::new(vec![].into_boxed_slice()).map_mut(|x| &mut x[..]);
-
-        let c: OwningRefMut<Box<Vec<u8>>, [u8]> = unsafe { a.map_owner(Box::new) };
-        let d: OwningRefMut<Box<Box<[u8]>>, [u8]> = unsafe { b.map_owner(Box::new) };
-
-        let _e: OwningRefMut<Box<dyn Erased>, [u8]> = c.erase_owner();
-        let _f: OwningRefMut<Box<dyn Erased>, [u8]> = d.erase_owner();
-    }
-
-    #[test]
-    fn total_erase_box() {
-        let a: OwningRefMut<Vec<u8>, [u8]> = OwningRefMut::new(vec![]).map_mut(|x| &mut x[..]);
-        let b: OwningRefMut<Box<[u8]>, [u8]> =
-            OwningRefMut::new(vec![].into_boxed_slice()).map_mut(|x| &mut x[..]);
-
-        let c: OwningRefMut<Box<Vec<u8>>, [u8]> = a.map_owner_box();
-        let d: OwningRefMut<Box<Box<[u8]>>, [u8]> = b.map_owner_box();
-
-        let _e: OwningRefMut<Box<dyn Erased>, [u8]> = c.erase_owner();
-        let _f: OwningRefMut<Box<dyn Erased>, [u8]> = d.erase_owner();
-    }
-
-    #[test]
-    fn try_map1() {
-        use std::any::Any;
-
-        let x = Box::new(123_i32);
-        let y: Box<dyn Any> = x;
-
-        assert!(OwningRefMut::new(y).try_map_mut(|x| x.downcast_mut::<i32>().ok_or(())).is_ok());
-    }
-
-    #[test]
-    fn try_map2() {
-        use std::any::Any;
-
-        let x = Box::new(123_i32);
-        let y: Box<dyn Any> = x;
-
-        assert!(!OwningRefMut::new(y).try_map_mut(|x| x.downcast_mut::<i32>().ok_or(())).is_err());
-    }
-
-    #[test]
-    fn try_map3() {
-        use std::any::Any;
-
-        let x = Box::new(123_i32);
-        let y: Box<dyn Any> = x;
-
-        assert!(OwningRefMut::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).is_ok());
-    }
-
-    #[test]
-    fn try_map4() {
-        use std::any::Any;
-
-        let x = Box::new(123_i32);
-        let y: Box<dyn Any> = x;
-
-        assert!(!OwningRefMut::new(y).try_map(|x| x.downcast_ref::<i32>().ok_or(())).is_err());
-    }
-
-    #[test]
-    fn into_owning_ref() {
-        use super::super::BoxRef;
-
-        let or: BoxRefMut<()> = Box::new(()).into();
-        let or: BoxRef<()> = or.into();
-        assert_eq!(&*or, &());
-    }
-
-    struct Foo {
-        u: u32,
-    }
-    struct Bar {
-        f: Foo,
-    }
-
-    #[test]
-    fn ref_mut() {
-        use std::cell::RefCell;
-
-        let a = RefCell::new(Bar { f: Foo { u: 42 } });
-        let mut b = OwningRefMut::new(a.borrow_mut());
-        assert_eq!(b.f.u, 42);
-        b.f.u = 43;
-        let mut c = b.map_mut(|x| &mut x.f);
-        assert_eq!(c.u, 43);
-        c.u = 44;
-        let mut d = c.map_mut(|x| &mut x.u);
-        assert_eq!(*d, 44);
-        *d = 45;
-        assert_eq!(*d, 45);
-    }
-}
diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs
index e8ee4fb76cc..ef1da85198f 100644
--- a/compiler/rustc_data_structures/src/sync.rs
+++ b/compiler/rustc_data_structures/src/sync.rs
@@ -7,9 +7,6 @@
 //! while the serial versions degenerate straightforwardly to serial execution.
 //! The operations include `join`, `parallel`, `par_iter`, and `par_for_each`.
 //!
-//! `rustc_erase_owner!` erases an `OwningRef` owner into `Erased` for the
-//! serial version and `Erased + Send + Sync` for the parallel version.
-//!
 //! Types
 //! -----
 //! The parallel versions of types provide various kinds of synchronization,
@@ -42,7 +39,7 @@
 //!
 //! [^2] `MTLockRef` is a typedef.
 
-use crate::owning_ref::{Erased, OwningRef};
+use crate::owned_slice::OwnedSlice;
 use std::collections::HashMap;
 use std::hash::{BuildHasher, Hash};
 use std::ops::{Deref, DerefMut};
@@ -57,18 +54,11 @@ mod vec;
 
 cfg_if! {
     if #[cfg(not(parallel_compiler))] {
-        pub auto trait Send {}
-        pub auto trait Sync {}
-
-        impl<T> Send for T {}
-        impl<T> Sync for T {}
+        pub unsafe auto trait Send {}
+        pub unsafe auto trait Sync {}
 
-        #[macro_export]
-        macro_rules! rustc_erase_owner {
-            ($v:expr) => {
-                $v.erase_owner()
-            }
-        }
+        unsafe impl<T> Send for T {}
+        unsafe impl<T> Sync for T {}
 
         use std::ops::Add;
 
@@ -197,7 +187,7 @@ cfg_if! {
             }
         }
 
-        pub type MetadataRef = OwningRef<Box<dyn Erased>, [u8]>;
+        pub type MetadataRef = OwnedSlice;
 
         pub use std::rc::Rc as Lrc;
         pub use std::rc::Weak as Weak;
@@ -380,20 +370,11 @@ cfg_if! {
             });
         }
 
-        pub type MetadataRef = OwningRef<Box<dyn Erased + Send + Sync>, [u8]>;
+        pub type MetadataRef = OwnedSlice;
 
         /// This makes locks panic if they are already held.
         /// It is only useful when you are running in a single thread
         const ERROR_CHECKING: bool = false;
-
-        #[macro_export]
-        macro_rules! rustc_erase_owner {
-            ($v:expr) => {{
-                let v = $v;
-                ::rustc_data_structures::sync::assert_send_val(&v);
-                v.erase_send_sync_owner()
-            }}
-        }
     }
 }
 
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 84114b27f41..426c6727adc 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -518,6 +518,8 @@ declare_features! (
     /// Allows dyn upcasting trait objects via supertraits.
     /// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
     (active, trait_upcasting, "1.56.0", Some(65991), None),
+    /// Allows for transmuting between arrays with sizes that contain generic consts.
+    (active, transmute_generic_consts, "CURRENT_RUSTC_VERSION", Some(109929), None),
     /// Allows #[repr(transparent)] on unions (RFC 2645).
     (active, transparent_unions, "1.37.0", Some(60405), None),
     /// Allows inconsistent bounds in where clauses.
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 6727173cd88..acca3fa2641 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -2336,10 +2336,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 FnMutDelegate {
                     regions: &mut |_| tcx.lifetimes.re_erased,
                     types: &mut |bv| {
-                        tcx.mk_placeholder(ty::PlaceholderType { universe, name: bv.kind })
+                        tcx.mk_placeholder(ty::PlaceholderType { universe, bound: bv })
                     },
                     consts: &mut |bv, ty| {
-                        tcx.mk_const(ty::PlaceholderConst { universe, name: bv }, ty)
+                        tcx.mk_const(ty::PlaceholderConst { universe, bound: bv }, ty)
                     },
                 },
             );
@@ -2525,11 +2525,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                             regions: &mut |_| tcx.lifetimes.re_erased,
                                             types: &mut |bv| tcx.mk_placeholder(ty::PlaceholderType {
                                                 universe,
-                                                name: bv.kind,
+                                                bound: bv,
                                             }),
                                             consts: &mut |bv, ty| tcx.mk_const(ty::PlaceholderConst {
                                                 universe,
-                                                name: bv
+                                                bound: bv,
                                             }, ty),
                                         })
                                     )
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 1b7475486dc..854974d1605 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -139,14 +139,14 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
     let name_str = intrinsic_name.as_str();
 
     let bound_vars = tcx.mk_bound_variable_kinds(&[
-        ty::BoundVariableKind::Region(ty::BrAnon(0, None)),
+        ty::BoundVariableKind::Region(ty::BrAnon(None)),
         ty::BoundVariableKind::Region(ty::BrEnv),
     ]);
     let mk_va_list_ty = |mutbl| {
         tcx.lang_items().va_list().map(|did| {
             let region = tcx.mk_re_late_bound(
                 ty::INNERMOST,
-                ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) },
+                ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) },
             );
             let env_region = tcx.mk_re_late_bound(
                 ty::INNERMOST,
@@ -387,8 +387,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
                 );
                 let discriminant_def_id = assoc_items[0];
 
-                let br =
-                    ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) };
+                let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) };
                 (
                     1,
                     vec![tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0))],
@@ -440,8 +439,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
             sym::nontemporal_store => (1, vec![tcx.mk_mut_ptr(param(0)), param(0)], tcx.mk_unit()),
 
             sym::raw_eq => {
-                let br =
-                    ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(0, None) };
+                let br = ty::BoundRegion { var: ty::BoundVar::from_u32(0), kind: ty::BrAnon(None) };
                 let param_ty = tcx.mk_imm_ref(tcx.mk_re_late_bound(ty::INNERMOST, br), param(0));
                 (1, vec![param_ty; 2], tcx.types.bool)
             }
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 2a9025d60ab..27e56180349 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -70,7 +70,6 @@ This API is completely unstable and subject to change.
 #![feature(lazy_cell)]
 #![feature(slice_partition_dedup)]
 #![feature(try_blocks)]
-#![feature(is_some_and)]
 #![feature(type_alias_impl_trait)]
 #![recursion_limit = "256"]
 
diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
index 9ecc870a70d..84ed8f3780e 100644
--- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
+++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs
@@ -240,7 +240,7 @@ pub fn resolve_interior<'a, 'tcx>(
 
             let mut counter = 0;
             let mut mk_bound_region = |span| {
-                let kind = ty::BrAnon(counter, span);
+                let kind = ty::BrAnon(span);
                 let var = ty::BoundVar::from_u32(counter);
                 counter += 1;
                 ty::BoundRegion { var, kind }
@@ -263,7 +263,7 @@ pub fn resolve_interior<'a, 'tcx>(
                     }
                     ty::ReLateBound(_, ty::BoundRegion { kind, .. })
                     | ty::ReFree(ty::FreeRegion { bound_region: kind, .. }) => match kind {
-                        ty::BoundRegionKind::BrAnon(_, span) => mk_bound_region(span),
+                        ty::BoundRegionKind::BrAnon(span) => mk_bound_region(span),
                         ty::BoundRegionKind::BrNamed(def_id, _) => {
                             mk_bound_region(Some(fcx.tcx.def_span(def_id)))
                         }
@@ -294,7 +294,7 @@ pub fn resolve_interior<'a, 'tcx>(
             FnMutDelegate {
                 regions: &mut |br| {
                     let kind = match br.kind {
-                        ty::BrAnon(_, span) => ty::BrAnon(counter, span),
+                        ty::BrAnon(span) => ty::BrAnon(span),
                         _ => br.kind,
                     };
                     let var = ty::BoundVar::from_usize(bound_vars.len());
diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs
index 901acffe1c8..106f5bcd755 100644
--- a/compiler/rustc_hir_typeck/src/intrinsicck.rs
+++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs
@@ -84,6 +84,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let skeleton_string = |ty: Ty<'tcx>, sk| match sk {
             Ok(SizeSkeleton::Known(size)) => format!("{} bits", size.bits()),
             Ok(SizeSkeleton::Pointer { tail, .. }) => format!("pointer to `{tail}`"),
+            Ok(SizeSkeleton::Generic(size)) => {
+                if let Some(size) = size.try_eval_target_usize(tcx, self.param_env) {
+                    format!("{size} bytes")
+                } else {
+                    format!("generic size {size}")
+                }
+            }
             Err(LayoutError::Unknown(bad)) => {
                 if bad == ty {
                     "this type does not have a fixed size".to_owned()
diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl
index 15780898dc6..1e43644be89 100644
--- a/compiler/rustc_infer/messages.ftl
+++ b/compiler/rustc_infer/messages.ftl
@@ -30,8 +30,8 @@ infer_source_kind_subdiag_let = {$kind ->
 }{$x_kind ->
     [has_name] , where the {$prefix_kind ->
         *[type] type for {$prefix}
-        [const_with_param] the value of const parameter
-        [const] the value of the constant
+        [const_with_param] value of const parameter
+        [const] value of the constant
     } `{$arg_name}` is specified
     [underscore] , where the placeholders `_` are specified
     *[empty] {""}
diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs
index ef543b1fb93..30f6af74b83 100644
--- a/compiler/rustc_infer/src/errors/note_and_explain.rs
+++ b/compiler/rustc_infer/src/errors/note_and_explain.rs
@@ -90,9 +90,8 @@ impl<'a> DescriptionCtx<'a> {
                             };
                             me.span = Some(sp);
                         }
-                        ty::BrAnon(idx, span) => {
-                            me.kind = "anon_num_here";
-                            me.num_arg = idx+1;
+                        ty::BrAnon(span) => {
+                            me.kind = "defined_here";
                             me.span = match span {
                                 Some(_) => span,
                                 None => Some(tcx.def_span(scope)),
diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
index 3bbd01f8273..e808911a38b 100644
--- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
+++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
@@ -772,7 +772,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
         r: ty::Region<'tcx>,
     ) -> ty::Region<'tcx> {
         let var = self.canonical_var(info, r.into());
-        let br = ty::BoundRegion { var, kind: ty::BrAnon(var.as_u32(), None) };
+        let br = ty::BoundRegion { var, kind: ty::BrAnon(None) };
         self.interner().mk_re_late_bound(self.binder_index, br)
     }
 
diff --git a/compiler/rustc_infer/src/infer/canonical/mod.rs b/compiler/rustc_infer/src/infer/canonical/mod.rs
index ce230afdab3..fbb2257bf67 100644
--- a/compiler/rustc_infer/src/infer/canonical/mod.rs
+++ b/compiler/rustc_infer/src/infer/canonical/mod.rs
@@ -125,9 +125,9 @@ impl<'tcx> InferCtxt<'tcx> {
                 ty.into()
             }
 
-            CanonicalVarKind::PlaceholderTy(ty::PlaceholderType { universe, name }) => {
+            CanonicalVarKind::PlaceholderTy(ty::PlaceholderType { universe, bound }) => {
                 let universe_mapped = universe_map(universe);
-                let placeholder_mapped = ty::PlaceholderType { universe: universe_mapped, name };
+                let placeholder_mapped = ty::PlaceholderType { universe: universe_mapped, bound };
                 self.tcx.mk_placeholder(placeholder_mapped).into()
             }
 
@@ -138,9 +138,9 @@ impl<'tcx> InferCtxt<'tcx> {
                 )
                 .into(),
 
-            CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion { universe, name }) => {
+            CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion { universe, bound }) => {
                 let universe_mapped = universe_map(universe);
-                let placeholder_mapped = ty::PlaceholderRegion { universe: universe_mapped, name };
+                let placeholder_mapped = ty::PlaceholderRegion { universe: universe_mapped, bound };
                 self.tcx.mk_re_placeholder(placeholder_mapped).into()
             }
 
@@ -152,9 +152,9 @@ impl<'tcx> InferCtxt<'tcx> {
                 )
                 .into(),
 
-            CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst { universe, name }, ty) => {
+            CanonicalVarKind::PlaceholderConst(ty::PlaceholderConst { universe, bound }, ty) => {
                 let universe_mapped = universe_map(universe);
-                let placeholder_mapped = ty::PlaceholderConst { universe: universe_mapped, name };
+                let placeholder_mapped = ty::PlaceholderConst { universe: universe_mapped, bound };
                 self.tcx.mk_const(placeholder_mapped, ty).into()
             }
         }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index c9956b60a56..86fca9797d0 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -170,15 +170,15 @@ fn msg_span_from_named_region<'tcx>(
         }
         ty::ReStatic => ("the static lifetime".to_owned(), alt_span),
         ty::RePlaceholder(ty::PlaceholderRegion {
-            name: ty::BoundRegionKind::BrNamed(def_id, name),
+            bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrNamed(def_id, name), .. },
             ..
         }) => (format!("the lifetime `{name}` as defined here"), Some(tcx.def_span(def_id))),
         ty::RePlaceholder(ty::PlaceholderRegion {
-            name: ty::BoundRegionKind::BrAnon(_, Some(span)),
+            bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(Some(span)), .. },
             ..
         }) => (format!("the anonymous lifetime defined here"), Some(span)),
         ty::RePlaceholder(ty::PlaceholderRegion {
-            name: ty::BoundRegionKind::BrAnon(_, None),
+            bound: ty::BoundRegion { kind: ty::BoundRegionKind::BrAnon(None), .. },
             ..
         }) => (format!("an anonymous lifetime"), None),
         _ => bug!("{:?}", region),
@@ -226,8 +226,8 @@ fn msg_span_from_early_bound_and_free_regions<'tcx>(
                         };
                         (text, sp)
                     }
-                    ty::BrAnon(idx, span) => (
-                        format!("the anonymous lifetime #{} defined here", idx + 1),
+                    ty::BrAnon(span) => (
+                        "the anonymous lifetime as defined here".to_string(),
                         match span {
                             Some(span) => span,
                             None => tcx.def_span(scope)
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index bde16fad821..d7b900ca02d 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -1191,11 +1191,14 @@ impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
                 have_turbofish,
             } = args;
             let generics = tcx.generics_of(generics_def_id);
-            if let Some(argument_index) = generics
+            if let Some(mut argument_index) = generics
                 .own_substs(substs)
                 .iter()
                 .position(|&arg| self.generic_arg_contains_target(arg))
             {
+                if generics.parent.is_none() && generics.has_self {
+                    argument_index += 1;
+                }
                 let substs = self.infcx.resolve_vars_if_possible(substs);
                 let generic_args = &generics.own_substs_no_defaults(tcx, substs)
                     [generics.own_counts().lifetimes..];
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs
index e8d94f0c04e..8a78a1956c9 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_relation.rs
@@ -16,22 +16,34 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
         match &self.error {
             Some(RegionResolutionError::ConcreteFailure(
                 SubregionOrigin::RelateRegionParamBound(span),
-                Region(Interned(RePlaceholder(ty::Placeholder { name: sub_name, .. }), _)),
-                Region(Interned(RePlaceholder(ty::Placeholder { name: sup_name, .. }), _)),
+                Region(Interned(
+                    RePlaceholder(ty::Placeholder {
+                        bound: ty::BoundRegion { kind: sub_name, .. },
+                        ..
+                    }),
+                    _,
+                )),
+                Region(Interned(
+                    RePlaceholder(ty::Placeholder {
+                        bound: ty::BoundRegion { kind: sup_name, .. },
+                        ..
+                    }),
+                    _,
+                )),
             )) => {
                 let span = *span;
                 let (sub_span, sub_symbol) = match sub_name {
                     ty::BrNamed(def_id, symbol) => {
                         (Some(self.tcx().def_span(def_id)), Some(symbol))
                     }
-                    ty::BrAnon(_, span) => (*span, None),
+                    ty::BrAnon(span) => (*span, None),
                     ty::BrEnv => (None, None),
                 };
                 let (sup_span, sup_symbol) = match sup_name {
                     ty::BrNamed(def_id, symbol) => {
                         (Some(self.tcx().def_span(def_id)), Some(symbol))
                     }
-                    ty::BrAnon(_, span) => (*span, None),
+                    ty::BrAnon(span) => (*span, None),
                     ty::BrEnv => (None, None),
                 };
                 let diag = match (sub_span, sup_span, sub_symbol, sup_symbol) {
diff --git a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
index d1897cf24b4..a63cfbc919c 100644
--- a/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
+++ b/compiler/rustc_infer/src/infer/higher_ranked/mod.rs
@@ -82,20 +82,20 @@ impl<'tcx> InferCtxt<'tcx> {
 
         let delegate = FnMutDelegate {
             regions: &mut |br: ty::BoundRegion| {
-                self.tcx.mk_re_placeholder(ty::PlaceholderRegion {
-                    universe: next_universe,
-                    name: br.kind,
-                })
+                self.tcx
+                    .mk_re_placeholder(ty::PlaceholderRegion { universe: next_universe, bound: br })
             },
             types: &mut |bound_ty: ty::BoundTy| {
                 self.tcx.mk_placeholder(ty::PlaceholderType {
                     universe: next_universe,
-                    name: bound_ty.kind,
+                    bound: bound_ty,
                 })
             },
             consts: &mut |bound_var: ty::BoundVar, ty| {
-                self.tcx
-                    .mk_const(ty::PlaceholderConst { universe: next_universe, name: bound_var }, ty)
+                self.tcx.mk_const(
+                    ty::PlaceholderConst { universe: next_universe, bound: bound_var },
+                    ty,
+                )
             },
         };
 
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 9903ffa90ba..b4f2ad0bb34 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -2130,13 +2130,17 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
 
         fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
             if let ty::Infer(_) = t.kind() {
+                let idx = {
+                    let idx = self.idx;
+                    self.idx += 1;
+                    idx
+                };
                 self.tcx.mk_placeholder(ty::PlaceholderType {
                     universe: ty::UniverseIndex::ROOT,
-                    name: ty::BoundTyKind::Anon({
-                        let idx = self.idx;
-                        self.idx += 1;
-                        idx
-                    }),
+                    bound: ty::BoundTy {
+                        var: ty::BoundVar::from_u32(idx),
+                        kind: ty::BoundTyKind::Anon,
+                    },
                 })
             } else {
                 t.super_fold_with(self)
@@ -2153,7 +2157,7 @@ fn replace_param_and_infer_substs_with_placeholder<'tcx>(
                 self.tcx.mk_const(
                     ty::PlaceholderConst {
                         universe: ty::UniverseIndex::ROOT,
-                        name: ty::BoundVar::from_u32({
+                        bound: ty::BoundVar::from_u32({
                             let idx = self.idx;
                             self.idx += 1;
                             idx
diff --git a/compiler/rustc_infer/src/infer/nll_relate/mod.rs b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
index 7616a996da1..9f7b26b87f4 100644
--- a/compiler/rustc_infer/src/infer/nll_relate/mod.rs
+++ b/compiler/rustc_infer/src/infer/nll_relate/mod.rs
@@ -296,7 +296,7 @@ where
                     universe
                 });
 
-                let placeholder = ty::PlaceholderRegion { universe, name: br.kind };
+                let placeholder = ty::PlaceholderRegion { universe, bound: br };
                 debug!(?placeholder);
                 let placeholder_reg = nll_delegate.next_placeholder_region(placeholder);
                 debug!(?placeholder_reg);
diff --git a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
index 89ada23c667..b8ba98fc0a9 100644
--- a/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
+++ b/compiler/rustc_infer/src/infer/region_constraints/leak_check.rs
@@ -290,9 +290,9 @@ impl<'me, 'tcx> LeakCheck<'me, 'tcx> {
     ) -> TypeError<'tcx> {
         debug!("error: placeholder={:?}, other_region={:?}", placeholder, other_region);
         if self.overly_polymorphic {
-            TypeError::RegionsOverlyPolymorphic(placeholder.name, other_region)
+            TypeError::RegionsOverlyPolymorphic(placeholder.bound.kind, other_region)
         } else {
-            TypeError::RegionsInsufficientlyPolymorphic(placeholder.name, other_region)
+            TypeError::RegionsInsufficientlyPolymorphic(placeholder.bound.kind, other_region)
         }
     }
 }
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 6a2fd5aa6e6..cadb6b1e23f 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -152,10 +152,6 @@ LLVMRustInsertPrivateGlobal(LLVMModuleRef M, LLVMTypeRef Ty) {
                                  nullptr));
 }
 
-extern "C" LLVMTypeRef LLVMRustMetadataTypeInContext(LLVMContextRef C) {
-  return wrap(Type::getMetadataTy(*unwrap(C)));
-}
-
 static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
   switch (Kind) {
   case AlwaysInline:
@@ -480,11 +476,6 @@ extern "C" bool LLVMRustInlineAsmVerify(LLVMTypeRef Ty, char *Constraints,
 #endif
 }
 
-extern "C" void LLVMRustAppendModuleInlineAsm(LLVMModuleRef M, const char *Asm,
-                                              size_t AsmLen) {
-  unwrap(M)->appendModuleInlineAsm(StringRef(Asm, AsmLen));
-}
-
 typedef DIBuilder *LLVMRustDIBuilderRef;
 
 template <typename DIT> DIT *unwrapDIPtr(LLVMMetadataRef Ref) {
@@ -753,10 +744,6 @@ extern "C" bool LLVMRustHasModuleFlag(LLVMModuleRef M, const char *Name,
   return unwrap(M)->getModuleFlag(StringRef(Name, Len)) != nullptr;
 }
 
-extern "C" LLVMValueRef LLVMRustMetadataAsValue(LLVMContextRef C, LLVMMetadataRef MD) {
-  return wrap(MetadataAsValue::get(*unwrap(C), unwrap(MD)));
-}
-
 extern "C" void LLVMRustGlobalAddMetadata(
     LLVMValueRef Global, unsigned Kind, LLVMMetadataRef MD) {
   unwrap<GlobalObject>(Global)->addMetadata(Kind, *unwrap<MDNode>(MD));
@@ -1153,6 +1140,8 @@ extern "C" void LLVMRustWriteValueToString(LLVMValueRef V,
 }
 
 // LLVMArrayType function does not support 64-bit ElementCount
+// FIXME: replace with LLVMArrayType2 when bumped minimal version to llvm-17
+// https://github.com/llvm/llvm-project/commit/35276f16e5a2cae0dfb49c0fbf874d4d2f177acc
 extern "C" LLVMTypeRef LLVMRustArrayType(LLVMTypeRef ElementTy,
                                          uint64_t ElementCount) {
   return wrap(ArrayType::get(unwrap(ElementTy), ElementCount));
@@ -1408,61 +1397,6 @@ extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
   return true;
 }
 
-extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
-                                                LLVMValueRef ParentPad,
-                                                unsigned ArgCount,
-                                                LLVMValueRef *LLArgs,
-                                                const char *Name) {
-  Value **Args = unwrap(LLArgs);
-  if (ParentPad == nullptr) {
-    Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
-    ParentPad = wrap(Constant::getNullValue(Ty));
-  }
-  return wrap(unwrap(B)->CreateCleanupPad(
-      unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
-}
-
-extern "C" LLVMValueRef LLVMRustBuildCleanupRet(LLVMBuilderRef B,
-                                                LLVMValueRef CleanupPad,
-                                                LLVMBasicBlockRef UnwindBB) {
-  CleanupPadInst *Inst = cast<CleanupPadInst>(unwrap(CleanupPad));
-  return wrap(unwrap(B)->CreateCleanupRet(Inst, unwrap(UnwindBB)));
-}
-
-extern "C" LLVMValueRef
-LLVMRustBuildCatchPad(LLVMBuilderRef B, LLVMValueRef ParentPad,
-                      unsigned ArgCount, LLVMValueRef *LLArgs, const char *Name) {
-  Value **Args = unwrap(LLArgs);
-  return wrap(unwrap(B)->CreateCatchPad(
-      unwrap(ParentPad), ArrayRef<Value *>(Args, ArgCount), Name));
-}
-
-extern "C" LLVMValueRef LLVMRustBuildCatchRet(LLVMBuilderRef B,
-                                              LLVMValueRef Pad,
-                                              LLVMBasicBlockRef BB) {
-  return wrap(unwrap(B)->CreateCatchRet(cast<CatchPadInst>(unwrap(Pad)),
-                                              unwrap(BB)));
-}
-
-extern "C" LLVMValueRef LLVMRustBuildCatchSwitch(LLVMBuilderRef B,
-                                                 LLVMValueRef ParentPad,
-                                                 LLVMBasicBlockRef BB,
-                                                 unsigned NumHandlers,
-                                                 const char *Name) {
-  if (ParentPad == nullptr) {
-    Type *Ty = Type::getTokenTy(unwrap(B)->getContext());
-    ParentPad = wrap(Constant::getNullValue(Ty));
-  }
-  return wrap(unwrap(B)->CreateCatchSwitch(unwrap(ParentPad), unwrap(BB),
-                                                 NumHandlers, Name));
-}
-
-extern "C" void LLVMRustAddHandler(LLVMValueRef CatchSwitchRef,
-                                   LLVMBasicBlockRef Handler) {
-  Value *CatchSwitch = unwrap(CatchSwitchRef);
-  cast<CatchSwitchInst>(CatchSwitch)->addHandler(unwrap(Handler));
-}
-
 extern "C" OperandBundleDef *LLVMRustBuildOperandBundleDef(const char *Name,
                                                            LLVMValueRef *Inputs,
                                                            unsigned NumInputs) {
@@ -1627,6 +1561,7 @@ extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
   LLVMSetLinkage(V, fromRust(RustLinkage));
 }
 
+// FIXME: replace with LLVMConstInBoundsGEP2 when bumped minimal version to llvm-14
 extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty,
                                                   LLVMValueRef ConstantVal,
                                                   LLVMValueRef *ConstantIndices,
@@ -1704,12 +1639,6 @@ extern "C" LLVMRustVisibility LLVMRustGetVisibility(LLVMValueRef V) {
   return toRust(LLVMGetVisibility(V));
 }
 
-// Oh hey, a binding that makes sense for once? (because LLVM’s own do not)
-extern "C" LLVMValueRef LLVMRustBuildIntCast(LLVMBuilderRef B, LLVMValueRef Val,
-                                             LLVMTypeRef DestTy, bool isSigned) {
-  return wrap(unwrap(B)->CreateIntCast(unwrap(Val), unwrap(DestTy), isSigned, ""));
-}
-
 extern "C" void LLVMRustSetVisibility(LLVMValueRef V,
                                       LLVMRustVisibility RustVisibility) {
   LLVMSetVisibility(V, fromRust(RustVisibility));
diff --git a/compiler/rustc_macros/Cargo.toml b/compiler/rustc_macros/Cargo.toml
index 547c8debb50..745983e7e86 100644
--- a/compiler/rustc_macros/Cargo.toml
+++ b/compiler/rustc_macros/Cargo.toml
@@ -10,8 +10,8 @@ proc-macro = true
 annotate-snippets = "0.9"
 fluent-bundle = "0.15.2"
 fluent-syntax = "0.11"
-synstructure = "0.12.1"
-syn = { version = "1", features = ["full"] }
+synstructure = "0.13.0"
+syn = { version = "2", features = ["full"] }
 proc-macro2 = "1"
 quote = "1"
 unic-langid = { version = "0.9.0", features = ["macros"] }
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
index 7fbe3bc2888..9b91627883a 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
@@ -1,8 +1,7 @@
 #![deny(unused_must_use)]
 
 use crate::diagnostics::error::{
-    invalid_nested_attr, span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err,
-    DiagnosticDeriveError,
+    span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError,
 };
 use crate::diagnostics::utils::{
     build_field_mapping, is_doc_comment, report_error_if_not_applied_to_span, report_type_error,
@@ -11,9 +10,8 @@ use crate::diagnostics::utils::{
 };
 use proc_macro2::{Ident, Span, TokenStream};
 use quote::{format_ident, quote};
-use syn::{
-    parse_quote, spanned::Spanned, Attribute, Meta, MetaList, MetaNameValue, NestedMeta, Path, Type,
-};
+use syn::Token;
+use syn::{parse_quote, spanned::Spanned, Attribute, Meta, Path, Type};
 use synstructure::{BindingInfo, Structure, VariantInfo};
 
 /// What kind of diagnostic is being derived - a fatal/error/warning or a lint?
@@ -77,7 +75,7 @@ impl DiagnosticDeriveBuilder {
         match ast.data {
             syn::Data::Struct(..) | syn::Data::Enum(..) => (),
             syn::Data::Union(..) => {
-                span_err(span, "diagnostic derives can only be used on structs and enums");
+                span_err(span, "diagnostic derives can only be used on structs and enums").emit();
             }
         }
 
@@ -160,8 +158,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
         };
 
         if let SubdiagnosticKind::MultipartSuggestion { .. } = subdiag {
-            let meta = attr.parse_meta()?;
-            throw_invalid_attr!(attr, &meta, |diag| diag
+            throw_invalid_attr!(attr, |diag| diag
                 .help("consider creating a `Subdiagnostic` instead"));
         }
 
@@ -191,71 +188,44 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
             return Ok(quote! {});
         }
 
-        let name = attr.path.segments.last().unwrap().ident.to_string();
+        let name = attr.path().segments.last().unwrap().ident.to_string();
         let name = name.as_str();
-        let meta = attr.parse_meta()?;
 
-        if name == "diag" {
-            let Meta::List(MetaList { ref nested, .. }) = meta else {
-                throw_invalid_attr!(
-                    attr,
-                    &meta
-                );
-            };
+        let mut first = true;
 
-            let mut nested_iter = nested.into_iter().peekable();
+        if name == "diag" {
+            let mut tokens = TokenStream::new();
+            attr.parse_nested_meta(|nested| {
+                let path = &nested.path;
 
-            match nested_iter.peek() {
-                Some(NestedMeta::Meta(Meta::Path(slug))) => {
-                    self.slug.set_once(slug.clone(), slug.span().unwrap());
-                    nested_iter.next();
+                if first && (nested.input.is_empty() || nested.input.peek(Token![,])) {
+                    self.slug.set_once(path.clone(), path.span().unwrap());
+                    first = false;
+                    return Ok(())
                 }
-                Some(NestedMeta::Meta(Meta::NameValue { .. })) => {}
-                Some(nested_attr) => throw_invalid_nested_attr!(attr, nested_attr, |diag| diag
-                    .help("a diagnostic slug is required as the first argument")),
-                None => throw_invalid_attr!(attr, &meta, |diag| diag
-                    .help("a diagnostic slug is required as the first argument")),
-            };
 
-            // Remaining attributes are optional, only `code = ".."` at the moment.
-            let mut tokens = TokenStream::new();
-            for nested_attr in nested_iter {
-                let (value, path) = match nested_attr {
-                    NestedMeta::Meta(Meta::NameValue(MetaNameValue {
-                        lit: syn::Lit::Str(value),
-                        path,
-                        ..
-                    })) => (value, path),
-                    NestedMeta::Meta(Meta::Path(_)) => {
-                        invalid_nested_attr(attr, nested_attr)
-                            .help("diagnostic slug must be the first argument")
-                            .emit();
-                        continue;
-                    }
-                    _ => {
-                        invalid_nested_attr(attr, nested_attr).emit();
-                        continue;
-                    }
+                first = false;
+
+                let Ok(nested) = nested.value() else {
+                    span_err(nested.input.span().unwrap(), "diagnostic slug must be the first argument").emit();
+                    return Ok(())
                 };
 
-                let nested_name = path.segments.last().unwrap().ident.to_string();
-                // Struct attributes are only allowed to be applied once, and the diagnostic
-                // changes will be set in the initialisation code.
-                let span = value.span().unwrap();
-                match nested_name.as_str() {
-                    "code" => {
-                        self.code.set_once((), span);
-
-                        let code = value.value();
-                        tokens.extend(quote! {
-                            #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string()));
-                        });
-                    }
-                    _ => invalid_nested_attr(attr, nested_attr)
-                        .help("only `code` is a valid nested attributes following the slug")
-                        .emit(),
+                if path.is_ident("code") {
+                    self.code.set_once((), path.span().unwrap());
+
+                    let code = nested.parse::<syn::LitStr>()?;
+                    tokens.extend(quote! {
+                        #diag.code(rustc_errors::DiagnosticId::Error(#code.to_string()));
+                    });
+                } else {
+                    span_err(path.span().unwrap(), "unknown argument").note("only the `code` parameter is valid after the slug").emit();
+
+                    // consume the buffer so we don't have syntax errors from syn
+                    let _ = nested.parse::<TokenStream>();
                 }
-            }
+                Ok(())
+            })?;
             return Ok(tokens);
         }
 
@@ -270,7 +240,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
                 Ok(self.add_subdiagnostic(&fn_ident, slug))
             }
             SubdiagnosticKind::Label | SubdiagnosticKind::Suggestion { .. } => {
-                throw_invalid_attr!(attr, &meta, |diag| diag
+                throw_invalid_attr!(attr, |diag| diag
                     .help("`#[label]` and `#[suggestion]` can only be applied to fields"));
             }
             SubdiagnosticKind::MultipartSuggestion { .. } => unreachable!(),
@@ -309,7 +279,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
                     return quote! {};
                 }
 
-                let name = attr.path.segments.last().unwrap().ident.to_string();
+                let name = attr.path().segments.last().unwrap().ident.to_string();
                 let needs_clone =
                     name == "primary_span" && matches!(inner_ty, FieldInnerTy::Vec(_));
                 let (binding, needs_destructure) = if needs_clone {
@@ -343,11 +313,10 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
         binding: TokenStream,
     ) -> Result<TokenStream, DiagnosticDeriveError> {
         let diag = &self.parent.diag;
-        let meta = attr.parse_meta()?;
 
-        let ident = &attr.path.segments.last().unwrap().ident;
+        let ident = &attr.path().segments.last().unwrap().ident;
         let name = ident.to_string();
-        match (&meta, name.as_str()) {
+        match (&attr.meta, name.as_str()) {
             // Don't need to do anything - by virtue of the attribute existing, the
             // `set_arg` call will not be generated.
             (Meta::Path(_), "skip_arg") => return Ok(quote! {}),
@@ -361,7 +330,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
                         });
                     }
                     DiagnosticDeriveKind::LintDiagnostic => {
-                        throw_invalid_attr!(attr, &meta, |diag| {
+                        throw_invalid_attr!(attr, |diag| {
                             diag.help("the `primary_span` field attribute is not valid for lint diagnostics")
                         })
                     }
@@ -378,26 +347,34 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
                     return Ok(quote! { #diag.subdiagnostic(#binding); });
                 }
             }
-            (Meta::List(MetaList { ref nested, .. }), "subdiagnostic") => {
-                if nested.len() == 1
-                    && let Some(NestedMeta::Meta(Meta::Path(path))) = nested.first()
-                    && path.is_ident("eager") {
-                        let handler = match &self.parent.kind {
-                            DiagnosticDeriveKind::Diagnostic { handler } => handler,
-                            DiagnosticDeriveKind::LintDiagnostic => {
-                                throw_invalid_attr!(attr, &meta, |diag| {
-                                    diag.help("eager subdiagnostics are not supported on lints")
-                                })
-                            }
-                        };
-                        return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); });
-                } else {
-                    throw_invalid_attr!(attr, &meta, |diag| {
-                        diag.help(
-                            "`eager` is the only supported nested attribute for `subdiagnostic`",
-                        )
-                    })
+            (Meta::List(meta_list), "subdiagnostic") => {
+                let err = || {
+                    span_err(
+                        meta_list.span().unwrap(),
+                        "`eager` is the only supported nested attribute for `subdiagnostic`",
+                    )
+                    .emit();
+                };
+
+                let Ok(p): Result<Path, _> = meta_list.parse_args() else {
+                    err();
+                    return Ok(quote! {});
+                };
+
+                if !p.is_ident("eager") {
+                    err();
+                    return Ok(quote! {});
                 }
+
+                let handler = match &self.parent.kind {
+                    DiagnosticDeriveKind::Diagnostic { handler } => handler,
+                    DiagnosticDeriveKind::LintDiagnostic => {
+                        throw_invalid_attr!(attr, |diag| {
+                            diag.help("eager subdiagnostics are not supported on lints")
+                        })
+                    }
+                };
+                return Ok(quote! { #diag.eager_subdiagnostic(#handler, #binding); });
             }
             _ => (),
         }
@@ -432,7 +409,7 @@ impl<'a> DiagnosticDeriveVariantBuilder<'a> {
                 code_init,
             } => {
                 if let FieldInnerTy::Vec(_) = info.ty {
-                    throw_invalid_attr!(attr, &meta, |diag| {
+                    throw_invalid_attr!(attr, |diag| {
                         diag
                         .note("`#[suggestion(...)]` applied to `Vec` field is ambiguous")
                         .help("to show a suggestion consisting of multiple parts, use a `Subdiagnostic` annotated with `#[multipart_suggestion(...)]`")
diff --git a/compiler/rustc_macros/src/diagnostics/error.rs b/compiler/rustc_macros/src/diagnostics/error.rs
index 2d62d593163..b37dc826d28 100644
--- a/compiler/rustc_macros/src/diagnostics/error.rs
+++ b/compiler/rustc_macros/src/diagnostics/error.rs
@@ -1,7 +1,7 @@
 use proc_macro::{Diagnostic, Level, MultiSpan};
 use proc_macro2::TokenStream;
 use quote::quote;
-use syn::{spanned::Spanned, Attribute, Error as SynError, Meta, NestedMeta};
+use syn::{spanned::Spanned, Attribute, Error as SynError, Meta};
 
 #[derive(Debug)]
 pub(crate) enum DiagnosticDeriveError {
@@ -53,6 +53,7 @@ fn path_to_string(path: &syn::Path) -> String {
 }
 
 /// Returns an error diagnostic on span `span` with msg `msg`.
+#[must_use]
 pub(crate) fn span_err(span: impl MultiSpan, msg: &str) -> Diagnostic {
     Diagnostic::spanned(span, Level::Error, msg)
 }
@@ -72,10 +73,10 @@ macro_rules! throw_span_err {
 pub(crate) use throw_span_err;
 
 /// Returns an error diagnostic for an invalid attribute.
-pub(crate) fn invalid_attr(attr: &Attribute, meta: &Meta) -> Diagnostic {
+pub(crate) fn invalid_attr(attr: &Attribute) -> Diagnostic {
     let span = attr.span().unwrap();
-    let path = path_to_string(&attr.path);
-    match meta {
+    let path = path_to_string(attr.path());
+    match attr.meta {
         Meta::Path(_) => span_err(span, &format!("`#[{path}]` is not a valid attribute")),
         Meta::NameValue(_) => {
             span_err(span, &format!("`#[{path} = ...]` is not a valid attribute"))
@@ -89,51 +90,11 @@ pub(crate) fn invalid_attr(attr: &Attribute, meta: &Meta) -> Diagnostic {
 ///
 /// For methods that return a `Result<_, DiagnosticDeriveError>`:
 macro_rules! throw_invalid_attr {
-    ($attr:expr, $meta:expr) => {{ throw_invalid_attr!($attr, $meta, |diag| diag) }};
-    ($attr:expr, $meta:expr, $f:expr) => {{
-        let diag = crate::diagnostics::error::invalid_attr($attr, $meta);
+    ($attr:expr) => {{ throw_invalid_attr!($attr, |diag| diag) }};
+    ($attr:expr, $f:expr) => {{
+        let diag = crate::diagnostics::error::invalid_attr($attr);
         return Err(crate::diagnostics::error::_throw_err(diag, $f));
     }};
 }
 
 pub(crate) use throw_invalid_attr;
-
-/// Returns an error diagnostic for an invalid nested attribute.
-pub(crate) fn invalid_nested_attr(attr: &Attribute, nested: &NestedMeta) -> Diagnostic {
-    let name = attr.path.segments.last().unwrap().ident.to_string();
-    let name = name.as_str();
-
-    let span = nested.span().unwrap();
-    let meta = match nested {
-        syn::NestedMeta::Meta(meta) => meta,
-        syn::NestedMeta::Lit(_) => {
-            return span_err(span, &format!("`#[{name}(\"...\")]` is not a valid attribute"));
-        }
-    };
-
-    let span = meta.span().unwrap();
-    let path = path_to_string(meta.path());
-    match meta {
-        Meta::NameValue(..) => {
-            span_err(span, &format!("`#[{name}({path} = ...)]` is not a valid attribute"))
-        }
-        Meta::Path(..) => span_err(span, &format!("`#[{name}({path})]` is not a valid attribute")),
-        Meta::List(..) => {
-            span_err(span, &format!("`#[{name}({path}(...))]` is not a valid attribute"))
-        }
-    }
-}
-
-/// Emit an error diagnostic for an invalid nested attribute (optionally performing additional
-/// decoration using the `FnOnce` passed in `diag`) and return `Err(ErrorHandled)`.
-///
-/// For methods that return a `Result<_, DiagnosticDeriveError>`:
-macro_rules! throw_invalid_nested_attr {
-    ($attr:expr, $nested_attr:expr) => {{ throw_invalid_nested_attr!($attr, $nested_attr, |diag| diag) }};
-    ($attr:expr, $nested_attr:expr, $f:expr) => {{
-        let diag = crate::diagnostics::error::invalid_nested_attr($attr, $nested_attr);
-        return Err(crate::diagnostics::error::_throw_err(diag, $f));
-    }};
-}
-
-pub(crate) use throw_invalid_nested_attr;
diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
index 90660fc1f93..62d49c1c64e 100644
--- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
@@ -1,8 +1,7 @@
 #![deny(unused_must_use)]
 
 use crate::diagnostics::error::{
-    invalid_attr, span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err,
-    DiagnosticDeriveError,
+    invalid_attr, span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError,
 };
 use crate::diagnostics::utils::{
     build_field_mapping, is_doc_comment, new_code_ident,
@@ -11,7 +10,7 @@ use crate::diagnostics::utils::{
 };
 use proc_macro2::TokenStream;
 use quote::{format_ident, quote};
-use syn::{spanned::Spanned, Attribute, Meta, MetaList, NestedMeta, Path};
+use syn::{spanned::Spanned, Attribute, Meta, MetaList, Path};
 use synstructure::{BindingInfo, Structure, VariantInfo};
 
 use super::utils::{build_suggestion_code, AllowMultipleAlternatives};
@@ -39,7 +38,8 @@ impl SubdiagnosticDeriveBuilder {
                     span_err(
                         span,
                         "`#[derive(Subdiagnostic)]` can only be used on structs and enums",
-                    );
+                    )
+                    .emit();
                 }
             }
 
@@ -192,7 +192,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
             };
 
             let Some(slug) = slug else {
-                let name = attr.path.segments.last().unwrap().ident.to_string();
+                let name = attr.path().segments.last().unwrap().ident.to_string();
                 let name = name.as_str();
 
                 throw_span_err!(
@@ -265,17 +265,18 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
         info: FieldInfo<'_>,
         clone_suggestion_code: bool,
     ) -> Result<TokenStream, DiagnosticDeriveError> {
-        let meta = attr.parse_meta()?;
-        match meta {
-            Meta::Path(path) => self.generate_field_code_inner_path(kind_stats, attr, info, path),
-            Meta::List(list @ MetaList { .. }) => self.generate_field_code_inner_list(
+        match &attr.meta {
+            Meta::Path(path) => {
+                self.generate_field_code_inner_path(kind_stats, attr, info, path.clone())
+            }
+            Meta::List(list) => self.generate_field_code_inner_list(
                 kind_stats,
                 attr,
                 info,
                 list,
                 clone_suggestion_code,
             ),
-            _ => throw_invalid_attr!(attr, &meta),
+            _ => throw_invalid_attr!(attr),
         }
     }
 
@@ -296,7 +297,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
             "skip_arg" => Ok(quote! {}),
             "primary_span" => {
                 if kind_stats.has_multipart_suggestion {
-                    invalid_attr(attr, &Meta::Path(path))
+                    invalid_attr(attr)
                         .help(
                             "multipart suggestions use one or more `#[suggestion_part]`s rather \
                             than one `#[primary_span]`",
@@ -309,7 +310,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
                     // FIXME(#100717): support `Option<Span>` on `primary_span` like in the
                     // diagnostic derive
                     if !matches!(info.ty, FieldInnerTy::Plain(_)) {
-                        throw_invalid_attr!(attr, &Meta::Path(path), |diag| {
+                        throw_invalid_attr!(attr, |diag| {
                             let diag = diag.note("there must be exactly one primary span");
 
                             if kind_stats.has_normal_suggestion {
@@ -335,7 +336,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
                     span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`")
                         .emit();
                 } else {
-                    invalid_attr(attr, &Meta::Path(path))
+                    invalid_attr(attr)
                         .help(
                             "`#[suggestion_part(...)]` is only valid in multipart suggestions, \
                              use `#[primary_span]` instead",
@@ -375,7 +376,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
                     span_attrs.push("primary_span")
                 }
 
-                invalid_attr(attr, &Meta::Path(path))
+                invalid_attr(attr)
                     .help(format!(
                         "only `{}`, `applicability` and `skip_arg` are valid field attributes",
                         span_attrs.join(", ")
@@ -394,7 +395,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
         kind_stats: KindsStatistics,
         attr: &Attribute,
         info: FieldInfo<'_>,
-        list: MetaList,
+        list: &MetaList,
         clone_suggestion_code: bool,
     ) -> Result<TokenStream, DiagnosticDeriveError> {
         let span = attr.span().unwrap();
@@ -405,7 +406,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
         match name {
             "suggestion_part" => {
                 if !kind_stats.has_multipart_suggestion {
-                    throw_invalid_attr!(attr, &Meta::List(list), |diag| {
+                    throw_invalid_attr!(attr, |diag| {
                         diag.help(
                             "`#[suggestion_part(...)]` is only valid in multipart suggestions",
                         )
@@ -417,31 +418,27 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
                 report_error_if_not_applied_to_span(attr, &info)?;
 
                 let mut code = None;
-                for nested_attr in list.nested.iter() {
-                    let NestedMeta::Meta(ref meta) = nested_attr else {
-                        throw_invalid_nested_attr!(attr, nested_attr);
-                    };
-
-                    let span = meta.span().unwrap();
-                    let nested_name = meta.path().segments.last().unwrap().ident.to_string();
-                    let nested_name = nested_name.as_str();
-
-                    match nested_name {
-                        "code" => {
-                            let code_field = new_code_ident();
-                            let formatting_init = build_suggestion_code(
-                                &code_field,
-                                meta,
-                                self,
-                                AllowMultipleAlternatives::No,
-                            );
-                            code.set_once((code_field, formatting_init), span);
-                        }
-                        _ => throw_invalid_nested_attr!(attr, nested_attr, |diag| {
-                            diag.help("`code` is the only valid nested attribute")
-                        }),
+
+                list.parse_nested_meta(|nested| {
+                    if nested.path.is_ident("code") {
+                        let code_field = new_code_ident();
+                        let span = nested.path.span().unwrap();
+                        let formatting_init = build_suggestion_code(
+                            &code_field,
+                            nested,
+                            self,
+                            AllowMultipleAlternatives::No,
+                        );
+                        code.set_once((code_field, formatting_init), span);
+                    } else {
+                        span_err(
+                            nested.path.span().unwrap(),
+                            "`code` is the only valid nested attribute",
+                        )
+                        .emit();
                     }
-                }
+                    Ok(())
+                })?;
 
                 let Some((code_field, formatting_init)) = code.value() else {
                     span_err(span, "`#[suggestion_part(...)]` attribute without `code = \"...\"`")
@@ -458,7 +455,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
                 };
                 Ok(quote! { suggestions.push((#binding, #code_field)); })
             }
-            _ => throw_invalid_attr!(attr, &Meta::List(list), |diag| {
+            _ => throw_invalid_attr!(attr, |diag| {
                 let mut span_attrs = vec![];
                 if kind_stats.has_multipart_suggestion {
                     span_attrs.push("suggestion_part");
diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs
index 65bb154d7f3..b9b09c66230 100644
--- a/compiler/rustc_macros/src/diagnostics/utils.rs
+++ b/compiler/rustc_macros/src/diagnostics/utils.rs
@@ -1,5 +1,5 @@
 use crate::diagnostics::error::{
-    span_err, throw_invalid_attr, throw_invalid_nested_attr, throw_span_err, DiagnosticDeriveError,
+    span_err, throw_invalid_attr, throw_span_err, DiagnosticDeriveError,
 };
 use proc_macro::Span;
 use proc_macro2::{Ident, TokenStream};
@@ -8,11 +8,13 @@ use std::cell::RefCell;
 use std::collections::{BTreeSet, HashMap};
 use std::fmt;
 use std::str::FromStr;
+use syn::meta::ParseNestedMeta;
+use syn::punctuated::Punctuated;
+use syn::{parenthesized, LitStr, Path, Token};
 use syn::{spanned::Spanned, Attribute, Field, Meta, Type, TypeTuple};
-use syn::{MetaList, MetaNameValue, NestedMeta, Path};
 use synstructure::{BindingInfo, VariantInfo};
 
-use super::error::{invalid_attr, invalid_nested_attr};
+use super::error::invalid_attr;
 
 thread_local! {
     pub static CODE_IDENT_COUNT: RefCell<u32> = RefCell::new(0);
@@ -60,8 +62,8 @@ pub(crate) fn report_type_error(
     attr: &Attribute,
     ty_name: &str,
 ) -> Result<!, DiagnosticDeriveError> {
-    let name = attr.path.segments.last().unwrap().ident.to_string();
-    let meta = attr.parse_meta()?;
+    let name = attr.path().segments.last().unwrap().ident.to_string();
+    let meta = &attr.meta;
 
     throw_span_err!(
         attr.span().unwrap(),
@@ -418,59 +420,62 @@ pub(super) enum AllowMultipleAlternatives {
     Yes,
 }
 
+fn parse_suggestion_values(
+    nested: ParseNestedMeta<'_>,
+    allow_multiple: AllowMultipleAlternatives,
+) -> syn::Result<Vec<LitStr>> {
+    let values = if let Ok(val) = nested.value() {
+        vec![val.parse()?]
+    } else {
+        let content;
+        parenthesized!(content in nested.input);
+
+        if let AllowMultipleAlternatives::No = allow_multiple {
+            span_err(
+                nested.input.span().unwrap(),
+                "expected exactly one string literal for `code = ...`",
+            )
+            .emit();
+            vec![]
+        } else {
+            let literals = Punctuated::<LitStr, Token![,]>::parse_terminated(&content);
+
+            match literals {
+                Ok(p) if p.is_empty() => {
+                    span_err(
+                        content.span().unwrap(),
+                        "expected at least one string literal for `code(...)`",
+                    )
+                    .emit();
+                    vec![]
+                }
+                Ok(p) => p.into_iter().collect(),
+                Err(_) => {
+                    span_err(
+                        content.span().unwrap(),
+                        "`code(...)` must contain only string literals",
+                    )
+                    .emit();
+                    vec![]
+                }
+            }
+        }
+    };
+
+    Ok(values)
+}
+
 /// Constructs the `format!()` invocation(s) necessary for a `#[suggestion*(code = "foo")]` or
 /// `#[suggestion*(code("foo", "bar"))]` attribute field
 pub(super) fn build_suggestion_code(
     code_field: &Ident,
-    meta: &Meta,
+    nested: ParseNestedMeta<'_>,
     fields: &impl HasFieldMap,
     allow_multiple: AllowMultipleAlternatives,
 ) -> TokenStream {
-    let values = match meta {
-        // `code = "foo"`
-        Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(s), .. }) => vec![s],
-        // `code("foo", "bar")`
-        Meta::List(MetaList { nested, .. }) => {
-            if let AllowMultipleAlternatives::No = allow_multiple {
-                span_err(
-                    meta.span().unwrap(),
-                    "expected exactly one string literal for `code = ...`",
-                )
-                .emit();
-                vec![]
-            } else if nested.is_empty() {
-                span_err(
-                    meta.span().unwrap(),
-                    "expected at least one string literal for `code(...)`",
-                )
-                .emit();
-                vec![]
-            } else {
-                nested
-                    .into_iter()
-                    .filter_map(|item| {
-                        if let NestedMeta::Lit(syn::Lit::Str(s)) = item {
-                            Some(s)
-                        } else {
-                            span_err(
-                                item.span().unwrap(),
-                                "`code(...)` must contain only string literals",
-                            )
-                            .emit();
-                            None
-                        }
-                    })
-                    .collect()
-            }
-        }
-        _ => {
-            span_err(
-                meta.span().unwrap(),
-                r#"`code = "..."`/`code(...)` must contain only string literals"#,
-            )
-            .emit();
-            vec![]
-        }
+    let values = match parse_suggestion_values(nested, allow_multiple) {
+        Ok(x) => x,
+        Err(e) => return e.into_compile_error(),
     };
 
     if let AllowMultipleAlternatives::Yes = allow_multiple {
@@ -601,11 +606,9 @@ impl SubdiagnosticKind {
 
         let span = attr.span().unwrap();
 
-        let name = attr.path.segments.last().unwrap().ident.to_string();
+        let name = attr.path().segments.last().unwrap().ident.to_string();
         let name = name.as_str();
 
-        let meta = attr.parse_meta()?;
-
         let mut kind = match name {
             "label" => SubdiagnosticKind::Label,
             "note" => SubdiagnosticKind::Note,
@@ -618,7 +621,7 @@ impl SubdiagnosticKind {
                     name.strip_prefix("suggestion").and_then(SuggestionKind::from_suffix)
                 {
                     if suggestion_kind != SuggestionKind::Normal {
-                        invalid_attr(attr, &meta)
+                        invalid_attr(attr)
                             .help(format!(
                                 r#"Use `#[suggestion(..., style = "{suggestion_kind}")]` instead"#
                             ))
@@ -635,7 +638,7 @@ impl SubdiagnosticKind {
                     name.strip_prefix("multipart_suggestion").and_then(SuggestionKind::from_suffix)
                 {
                     if suggestion_kind != SuggestionKind::Normal {
-                        invalid_attr(attr, &meta)
+                        invalid_attr(attr)
                             .help(format!(
                                 r#"Use `#[multipart_suggestion(..., style = "{suggestion_kind}")]` instead"#
                             ))
@@ -647,16 +650,16 @@ impl SubdiagnosticKind {
                         applicability: None,
                     }
                 } else {
-                    throw_invalid_attr!(attr, &meta);
+                    throw_invalid_attr!(attr);
                 }
             }
         };
 
-        let nested = match meta {
-            Meta::List(MetaList { ref nested, .. }) => {
+        let list = match &attr.meta {
+            Meta::List(list) => {
                 // An attribute with properties, such as `#[suggestion(code = "...")]` or
                 // `#[error(some::slug)]`
-                nested
+                list
             }
             Meta::Path(_) => {
                 // An attribute without a slug or other properties, such as `#[note]` - return
@@ -678,69 +681,68 @@ impl SubdiagnosticKind {
                 }
             }
             _ => {
-                throw_invalid_attr!(attr, &meta)
+                throw_invalid_attr!(attr)
             }
         };
 
         let mut code = None;
         let mut suggestion_kind = None;
 
-        let mut nested_iter = nested.into_iter().peekable();
+        let mut first = true;
+        let mut slug = None;
 
-        // Peek at the first nested attribute: if it's a slug path, consume it.
-        let slug = if let Some(NestedMeta::Meta(Meta::Path(path))) = nested_iter.peek() {
-            let path = path.clone();
-            // Advance the iterator.
-            nested_iter.next();
-            Some(path)
-        } else {
-            None
-        };
-
-        for nested_attr in nested_iter {
-            let meta = match nested_attr {
-                NestedMeta::Meta(ref meta) => meta,
-                NestedMeta::Lit(_) => {
-                    invalid_nested_attr(attr, nested_attr).emit();
-                    continue;
+        list.parse_nested_meta(|nested| {
+            if nested.input.is_empty() || nested.input.peek(Token![,]) {
+                if first {
+                    slug = Some(nested.path);
+                } else {
+                    span_err(nested.input.span().unwrap(), "a diagnostic slug must be the first argument to the attribute").emit();
                 }
-            };
 
-            let span = meta.span().unwrap();
-            let nested_name = meta.path().segments.last().unwrap().ident.to_string();
+                first = false;
+                return Ok(());
+            }
+
+            first = false;
+
+            let nested_name = nested.path.segments.last().unwrap().ident.to_string();
             let nested_name = nested_name.as_str();
 
-            let string_value = match meta {
-                Meta::NameValue(MetaNameValue { lit: syn::Lit::Str(value), .. }) => Some(value),
+            let path_span = nested.path.span().unwrap();
+            let val_span = nested.input.span().unwrap();
 
-                Meta::Path(_) => throw_invalid_nested_attr!(attr, nested_attr, |diag| {
-                    diag.help("a diagnostic slug must be the first argument to the attribute")
-                }),
-                _ => None,
-            };
+            macro_rules! get_string {
+                () => {{
+                    let Ok(value) = nested.value().and_then(|x| x.parse::<LitStr>()) else {
+                        span_err(val_span, "expected `= \"xxx\"`").emit();
+                        return Ok(());
+                    };
+                    value
+                }};
+            }
+
+            let mut has_errors = false;
+            let input = nested.input;
 
             match (nested_name, &mut kind) {
                 ("code", SubdiagnosticKind::Suggestion { code_field, .. }) => {
                     let code_init = build_suggestion_code(
                         code_field,
-                        meta,
+                        nested,
                         fields,
                         AllowMultipleAlternatives::Yes,
                     );
-                    code.set_once(code_init, span);
+                    code.set_once(code_init, path_span);
                 }
                 (
                     "applicability",
                     SubdiagnosticKind::Suggestion { ref mut applicability, .. }
                     | SubdiagnosticKind::MultipartSuggestion { ref mut applicability, .. },
                 ) => {
-                    let Some(value) = string_value else {
-                        invalid_nested_attr(attr, nested_attr).emit();
-                        continue;
-                    };
-
+                    let value = get_string!();
                     let value = Applicability::from_str(&value.value()).unwrap_or_else(|()| {
-                        span_err(span, "invalid applicability").emit();
+                        span_err(value.span().unwrap(), "invalid applicability").emit();
+                        has_errors = true;
                         Applicability::Unspecified
                     });
                     applicability.set_once(value, span);
@@ -750,15 +752,13 @@ impl SubdiagnosticKind {
                     SubdiagnosticKind::Suggestion { .. }
                     | SubdiagnosticKind::MultipartSuggestion { .. },
                 ) => {
-                    let Some(value) = string_value else {
-                        invalid_nested_attr(attr, nested_attr).emit();
-                        continue;
-                    };
+                    let value = get_string!();
 
                     let value = value.value().parse().unwrap_or_else(|()| {
                         span_err(value.span().unwrap(), "invalid suggestion style")
                             .help("valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only`")
                             .emit();
+                        has_errors = true;
                         SuggestionKind::Normal
                     });
 
@@ -767,22 +767,32 @@ impl SubdiagnosticKind {
 
                 // Invalid nested attribute
                 (_, SubdiagnosticKind::Suggestion { .. }) => {
-                    invalid_nested_attr(attr, nested_attr)
+                    span_err(path_span, "invalid nested attribute")
                         .help(
                             "only `style`, `code` and `applicability` are valid nested attributes",
                         )
                         .emit();
+                    has_errors = true;
                 }
                 (_, SubdiagnosticKind::MultipartSuggestion { .. }) => {
-                    invalid_nested_attr(attr, nested_attr)
+                    span_err(path_span, "invalid nested attribute")
                         .help("only `style` and `applicability` are valid nested attributes")
-                        .emit()
+                        .emit();
+                    has_errors = true;
                 }
                 _ => {
-                    invalid_nested_attr(attr, nested_attr).emit();
+                    span_err(path_span, "invalid nested attribute").emit();
+                    has_errors = true;
                 }
             }
-        }
+
+            if has_errors {
+                // Consume the rest of the input to avoid spamming errors
+                let _ = input.parse::<TokenStream>();
+            }
+
+            Ok(())
+        })?;
 
         match kind {
             SubdiagnosticKind::Suggestion {
@@ -845,5 +855,5 @@ pub(super) fn should_generate_set_arg(field: &Field) -> bool {
 }
 
 pub(super) fn is_doc_comment(attr: &Attribute) -> bool {
-    attr.path.segments.last().unwrap().ident == "doc"
+    attr.path().segments.last().unwrap().ident == "doc"
 }
diff --git a/compiler/rustc_macros/src/hash_stable.rs b/compiler/rustc_macros/src/hash_stable.rs
index 63bdcea87f8..75a2f7009c2 100644
--- a/compiler/rustc_macros/src/hash_stable.rs
+++ b/compiler/rustc_macros/src/hash_stable.rs
@@ -1,6 +1,6 @@
 use proc_macro2::{self, Ident};
 use quote::quote;
-use syn::{self, parse_quote, Meta, NestedMeta};
+use syn::{self, parse_quote};
 
 struct Attributes {
     ignore: bool,
@@ -10,32 +10,29 @@ struct Attributes {
 fn parse_attributes(field: &syn::Field) -> Attributes {
     let mut attrs = Attributes { ignore: false, project: None };
     for attr in &field.attrs {
-        if let Ok(meta) = attr.parse_meta() {
-            if !meta.path().is_ident("stable_hasher") {
-                continue;
+        let meta = &attr.meta;
+        if !meta.path().is_ident("stable_hasher") {
+            continue;
+        }
+        let mut any_attr = false;
+        let _ = attr.parse_nested_meta(|nested| {
+            if nested.path.is_ident("ignore") {
+                attrs.ignore = true;
+                any_attr = true;
             }
-            let mut any_attr = false;
-            if let Meta::List(list) = meta {
-                for nested in list.nested.iter() {
-                    if let NestedMeta::Meta(meta) = nested {
-                        if meta.path().is_ident("ignore") {
-                            attrs.ignore = true;
-                            any_attr = true;
-                        }
-                        if meta.path().is_ident("project") {
-                            if let Meta::List(list) = meta {
-                                if let Some(NestedMeta::Meta(meta)) = list.nested.iter().next() {
-                                    attrs.project = meta.path().get_ident().cloned();
-                                    any_attr = true;
-                                }
-                            }
-                        }
+            if nested.path.is_ident("project") {
+                let _ = nested.parse_nested_meta(|meta| {
+                    if attrs.project.is_none() {
+                        attrs.project = meta.path.get_ident().cloned();
                     }
-                }
-            }
-            if !any_attr {
-                panic!("error parsing stable_hasher");
+                    any_attr = true;
+                    Ok(())
+                });
             }
+            Ok(())
+        });
+        if !any_attr {
+            panic!("error parsing stable_hasher");
         }
     }
     attrs
diff --git a/compiler/rustc_macros/src/newtype.rs b/compiler/rustc_macros/src/newtype.rs
index 89ea89cf502..78a6f74887d 100644
--- a/compiler/rustc_macros/src/newtype.rs
+++ b/compiler/rustc_macros/src/newtype.rs
@@ -25,7 +25,7 @@ impl Parse for Newtype {
         let mut encodable = true;
         let mut ord = true;
 
-        attrs.retain(|attr| match attr.path.get_ident() {
+        attrs.retain(|attr| match attr.path().get_ident() {
             Some(ident) => match &*ident.to_string() {
                 "custom_encodable" => {
                     encodable = false;
@@ -36,22 +36,22 @@ impl Parse for Newtype {
                     false
                 }
                 "max" => {
-                    let Ok(Meta::NameValue(literal) )= attr.parse_meta() else {
+                    let Meta::NameValue(MetaNameValue { value: Expr::Lit(lit), .. }) = &attr.meta else {
                         panic!("#[max = NUMBER] attribute requires max value");
                     };
 
-                    if let Some(old) = max.replace(literal.lit) {
+                    if let Some(old) = max.replace(lit.lit.clone()) {
                         panic!("Specified multiple max: {old:?}");
                     }
 
                     false
                 }
                 "debug_format" => {
-                    let Ok(Meta::NameValue(literal) )= attr.parse_meta() else {
+                    let Meta::NameValue(MetaNameValue { value: Expr::Lit(lit), .. }) = &attr.meta else {
                         panic!("#[debug_format = FMT] attribute requires a format");
                     };
 
-                    if let Some(old) = debug_format.replace(literal.lit) {
+                    if let Some(old) = debug_format.replace(lit.lit.clone()) {
                         panic!("Specified multiple debug format options: {old:?}");
                     }
 
diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs
index 08e42a8a08f..f85ba38003c 100644
--- a/compiler/rustc_macros/src/query.rs
+++ b/compiler/rustc_macros/src/query.rs
@@ -15,7 +15,7 @@ mod kw {
 /// Ensures only doc comment attributes are used
 fn check_attributes(attrs: Vec<Attribute>) -> Result<Vec<Attribute>> {
     let inner = |attr: Attribute| {
-        if !attr.path.is_ident("doc") {
+        if !attr.path().is_ident("doc") {
             Err(Error::new(attr.span(), "attributes not supported on queries"))
         } else if attr.style != AttrStyle::Outer {
             Err(Error::new(
@@ -48,7 +48,7 @@ impl Parse for Query {
         let name: Ident = input.parse()?;
         let arg_content;
         parenthesized!(arg_content in input);
-        let key = arg_content.parse()?;
+        let key = Pat::parse_single(&arg_content)?;
         arg_content.parse::<Token![:]>()?;
         let arg = arg_content.parse()?;
         let result = input.parse()?;
@@ -158,7 +158,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
             } else {
                 None
             };
-            let list = attr_content.parse_terminated(Expr::parse)?;
+            let list = attr_content.parse_terminated(Expr::parse, Token![,])?;
             try_insert!(desc = (tcx, list));
         } else if modifier == "cache_on_disk_if" {
             // Parse a cache modifier like:
@@ -166,7 +166,7 @@ fn parse_query_modifiers(input: ParseStream<'_>) -> Result<QueryModifiers> {
             let args = if input.peek(token::Paren) {
                 let args;
                 parenthesized!(args in input);
-                let tcx = args.parse()?;
+                let tcx = Pat::parse_single(&args)?;
                 Some(tcx)
             } else {
                 None
diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs
index 388e254cd64..5ee4d879313 100644
--- a/compiler/rustc_macros/src/type_foldable.rs
+++ b/compiler/rustc_macros/src/type_foldable.rs
@@ -1,5 +1,5 @@
 use quote::{quote, ToTokens};
-use syn::{parse_quote, Attribute, Meta, NestedMeta};
+use syn::parse_quote;
 
 pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
     if let syn::Data::Union(_) = s.ast().data {
@@ -17,21 +17,20 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::
         vi.construct(|_, index| {
             let bind = &bindings[index];
 
+            let mut fixed = false;
+
             // retain value of fields with #[type_foldable(identity)]
-            let fixed = bind
-                .ast()
-                .attrs
-                .iter()
-                .map(Attribute::parse_meta)
-                .filter_map(Result::ok)
-                .flat_map(|attr| match attr {
-                    Meta::List(list) if list.path.is_ident("type_foldable") => list.nested,
-                    _ => Default::default(),
-                })
-                .any(|nested| match nested {
-                    NestedMeta::Meta(Meta::Path(path)) => path.is_ident("identity"),
-                    _ => false,
+            bind.ast().attrs.iter().for_each(|x| {
+                if !x.path().is_ident("type_foldable") {
+                    return;
+                }
+                let _ = x.parse_nested_meta(|nested| {
+                    if nested.path.is_ident("identity") {
+                        fixed = true;
+                    }
+                    Ok(())
                 });
+            });
 
             if fixed {
                 bind.to_token_stream()
diff --git a/compiler/rustc_macros/src/type_visitable.rs b/compiler/rustc_macros/src/type_visitable.rs
index f6f4c4779c3..dcd505a105e 100644
--- a/compiler/rustc_macros/src/type_visitable.rs
+++ b/compiler/rustc_macros/src/type_visitable.rs
@@ -1,5 +1,5 @@
 use quote::quote;
-use syn::{parse_quote, Attribute, Meta, NestedMeta};
+use syn::parse_quote;
 
 pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
     if let syn::Data::Union(_) = s.ast().data {
@@ -8,19 +8,21 @@ pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:
 
     // ignore fields with #[type_visitable(ignore)]
     s.filter(|bi| {
-        !bi.ast()
-            .attrs
-            .iter()
-            .map(Attribute::parse_meta)
-            .filter_map(Result::ok)
-            .flat_map(|attr| match attr {
-                Meta::List(list) if list.path.is_ident("type_visitable") => list.nested,
-                _ => Default::default(),
-            })
-            .any(|nested| match nested {
-                NestedMeta::Meta(Meta::Path(path)) => path.is_ident("ignore"),
-                _ => false,
-            })
+        let mut ignored = false;
+
+        bi.ast().attrs.iter().for_each(|attr| {
+            if !attr.path().is_ident("type_visitable") {
+                return;
+            }
+            let _ = attr.parse_nested_meta(|nested| {
+                if nested.path.is_ident("ignore") {
+                    ignored = true;
+                }
+                Ok(())
+            });
+        });
+
+        !ignored
     });
 
     if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs
index 880da5ca593..81e62eccb8a 100644
--- a/compiler/rustc_metadata/src/lib.rs
+++ b/compiler/rustc_metadata/src/lib.rs
@@ -22,8 +22,6 @@ extern crate proc_macro;
 extern crate rustc_macros;
 #[macro_use]
 extern crate rustc_middle;
-#[macro_use]
-extern crate rustc_data_structures;
 
 #[macro_use]
 extern crate tracing;
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index 79c42a128e7..2515269ea2f 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -218,7 +218,7 @@ use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER};
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::memmap::Mmap;
-use rustc_data_structures::owning_ref::OwningRef;
+use rustc_data_structures::owned_slice::slice_owned;
 use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::MetadataRef;
 use rustc_errors::{DiagnosticArgValue, FatalError, IntoDiagnosticArg};
@@ -236,6 +236,7 @@ use rustc_target::spec::{Target, TargetTriple};
 use snap::read::FrameDecoder;
 use std::borrow::Cow;
 use std::io::{Read, Result as IoResult, Write};
+use std::ops::Deref;
 use std::path::{Path, PathBuf};
 use std::{cmp, fmt};
 
@@ -814,15 +815,14 @@ fn get_metadata_section<'p>(
             // Assume the decompressed data will be at least the size of the compressed data, so we
             // don't have to grow the buffer as much.
             let mut inflated = Vec::with_capacity(compressed_bytes.len());
-            match FrameDecoder::new(compressed_bytes).read_to_end(&mut inflated) {
-                Ok(_) => rustc_erase_owner!(OwningRef::new(inflated).map_owner_box()),
-                Err(_) => {
-                    return Err(MetadataError::LoadFailure(format!(
-                        "failed to decompress metadata: {}",
-                        filename.display()
-                    )));
-                }
-            }
+            FrameDecoder::new(compressed_bytes).read_to_end(&mut inflated).map_err(|_| {
+                MetadataError::LoadFailure(format!(
+                    "failed to decompress metadata: {}",
+                    filename.display()
+                ))
+            })?;
+
+            slice_owned(inflated, Deref::deref)
         }
         CrateFlavor::Rmeta => {
             // mmap the file, because only a small fraction of it is read.
@@ -840,7 +840,7 @@ fn get_metadata_section<'p>(
                 ))
             })?;
 
-            rustc_erase_owner!(OwningRef::new(mmap).map_owner_box())
+            slice_owned(mmap, Deref::deref)
         }
     };
     let blob = MetadataBlob::new(raw_bytes);
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 21ac7e201f9..852c6d96469 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -51,12 +51,6 @@ mod cstore_impl;
 #[derive(Clone)]
 pub(crate) struct MetadataBlob(Lrc<MetadataRef>);
 
-// This is needed so we can create an OwningRef into the blob.
-// The data behind a `MetadataBlob` has a stable address because it is
-// contained within an Rc/Arc.
-unsafe impl rustc_data_structures::owning_ref::StableAddress for MetadataBlob {}
-
-// This is needed so we can create an OwningRef into the blob.
 impl std::ops::Deref for MetadataBlob {
     type Target = [u8];
 
diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
index a6133f1b417..02cab561b8f 100644
--- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
+++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs
@@ -1,14 +1,14 @@
 use crate::rmeta::DecodeContext;
 use crate::rmeta::EncodeContext;
-use crate::rmeta::MetadataBlob;
-use rustc_data_structures::owning_ref::OwningRef;
+use rustc_data_structures::owned_slice::slice_owned;
+use rustc_data_structures::owned_slice::OwnedSlice;
 use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap};
 use rustc_middle::parameterized_over_tcx;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use rustc_span::def_id::{DefIndex, DefPathHash};
 
 pub(crate) enum DefPathHashMapRef<'tcx> {
-    OwnedFromMetadata(odht::HashTable<HashMapConfig, OwningRef<MetadataBlob, [u8]>>),
+    OwnedFromMetadata(odht::HashTable<HashMapConfig, OwnedSlice>),
     BorrowedFromTcx(&'tcx DefPathHashMap),
 }
 
@@ -50,11 +50,11 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for DefPathHashMapRef<'static>
 
         let len = d.read_usize();
         let pos = d.position();
-        let o = OwningRef::new(d.blob().clone()).map(|x| &x[pos..pos + len]);
+        let o = slice_owned(d.blob().clone(), |blob| &blob[pos..pos + len]);
 
-        // Although we already have the data we need via the OwningRef, we still need
-        // to advance the DecodeContext's position so it's in a valid state after
-        // the method. We use read_raw_bytes() for that.
+        // Although we already have the data we need via the `OwnedSlice`, we still need
+        // to advance the `DecodeContext`'s position so it's in a valid state after
+        // the method. We use `read_raw_bytes()` for that.
         let _ = d.read_raw_bytes(len);
 
         let inner = odht::HashTable::from_raw_bytes(o).unwrap_or_else(|e| {
diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs
index 2f42849f390..f668c4e77be 100644
--- a/compiler/rustc_middle/src/infer/canonical.rs
+++ b/compiler/rustc_middle/src/infer/canonical.rs
@@ -149,15 +149,15 @@ impl<'tcx> CanonicalVarInfo<'tcx> {
         }
     }
 
-    pub fn expect_anon_placeholder(self) -> u32 {
+    pub fn expect_placeholder_index(self) -> usize {
         match self.kind {
             CanonicalVarKind::Ty(_)
             | CanonicalVarKind::Region(_)
             | CanonicalVarKind::Const(_, _) => bug!("expected placeholder: {self:?}"),
 
-            CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.name.expect_anon(),
-            CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.name.expect_anon(),
-            CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.name.as_u32(),
+            CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.bound.var.as_usize(),
+            CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.bound.var.as_usize(),
+            CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.bound.as_usize(),
         }
     }
 }
@@ -411,7 +411,7 @@ impl<'tcx> CanonicalVarValues<'tcx> {
                         CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => {
                             let br = ty::BoundRegion {
                                 var: ty::BoundVar::from_usize(i),
-                                kind: ty::BrAnon(i as u32, None),
+                                kind: ty::BrAnon(None),
                             };
                             tcx.mk_re_late_bound(ty::INNERMOST, br).into()
                         }
diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs
index eb860c04de2..b898e85fa71 100644
--- a/compiler/rustc_middle/src/mir/patch.rs
+++ b/compiler/rustc_middle/src/mir/patch.rs
@@ -12,6 +12,9 @@ pub struct MirPatch<'tcx> {
     new_statements: Vec<(Location, StatementKind<'tcx>)>,
     new_locals: Vec<LocalDecl<'tcx>>,
     resume_block: Option<BasicBlock>,
+    // Only for unreachable in cleanup path.
+    unreachable_cleanup_block: Option<BasicBlock>,
+    terminate_block: Option<BasicBlock>,
     body_span: Span,
     next_local: usize,
 }
@@ -25,14 +28,31 @@ impl<'tcx> MirPatch<'tcx> {
             new_locals: vec![],
             next_local: body.local_decls.len(),
             resume_block: None,
+            unreachable_cleanup_block: None,
+            terminate_block: None,
             body_span: body.span,
         };
 
-        // Check if we already have a resume block
         for (bb, block) in body.basic_blocks.iter_enumerated() {
+            // Check if we already have a resume block
             if let TerminatorKind::Resume = block.terminator().kind && block.statements.is_empty() {
                 result.resume_block = Some(bb);
-                break;
+                continue;
+            }
+
+            // Check if we already have an unreachable block
+            if let TerminatorKind::Unreachable = block.terminator().kind
+                && block.statements.is_empty()
+                && block.is_cleanup
+            {
+                result.unreachable_cleanup_block = Some(bb);
+                continue;
+            }
+
+            // Check if we already have a terminate block
+            if let TerminatorKind::Terminate = block.terminator().kind && block.statements.is_empty() {
+                result.terminate_block = Some(bb);
+                continue;
             }
         }
 
@@ -56,6 +76,40 @@ impl<'tcx> MirPatch<'tcx> {
         bb
     }
 
+    pub fn unreachable_cleanup_block(&mut self) -> BasicBlock {
+        if let Some(bb) = self.unreachable_cleanup_block {
+            return bb;
+        }
+
+        let bb = self.new_block(BasicBlockData {
+            statements: vec![],
+            terminator: Some(Terminator {
+                source_info: SourceInfo::outermost(self.body_span),
+                kind: TerminatorKind::Unreachable,
+            }),
+            is_cleanup: true,
+        });
+        self.unreachable_cleanup_block = Some(bb);
+        bb
+    }
+
+    pub fn terminate_block(&mut self) -> BasicBlock {
+        if let Some(bb) = self.terminate_block {
+            return bb;
+        }
+
+        let bb = self.new_block(BasicBlockData {
+            statements: vec![],
+            terminator: Some(Terminator {
+                source_info: SourceInfo::outermost(self.body_span),
+                kind: TerminatorKind::Terminate,
+            }),
+            is_cleanup: true,
+        });
+        self.terminate_block = Some(bb);
+        bb
+    }
+
     pub fn is_patched(&self, bb: BasicBlock) -> bool {
         self.patch_map[bb].is_some()
     }
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 68561cf6dd7..cfdf1dcf5c0 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -411,10 +411,8 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
     pub fn bind(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self {
         let inner = tcx.fold_regions(ty, |r, depth| match r.kind() {
             ty::ReVar(vid) => {
-                let br = ty::BoundRegion {
-                    var: ty::BoundVar::new(vid.index()),
-                    kind: ty::BrAnon(vid.as_u32(), None),
-                };
+                let br =
+                    ty::BoundRegion { var: ty::BoundVar::new(vid.index()), kind: ty::BrAnon(None) };
                 tcx.mk_re_late_bound(depth, br)
             }
             _ => bug!("unexpected region in ClosureOutlivesSubjectTy: {r:?}"),
diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs
index 1a23f9dadd4..2165403da26 100644
--- a/compiler/rustc_middle/src/mir/spanview.rs
+++ b/compiler/rustc_middle/src/mir/spanview.rs
@@ -262,7 +262,7 @@ pub fn terminator_kind_name(term: &Terminator<'_>) -> &'static str {
         Goto { .. } => "Goto",
         SwitchInt { .. } => "SwitchInt",
         Resume => "Resume",
-        Abort => "Abort",
+        Terminate => "Terminate",
         Return => "Return",
         Unreachable => "Unreachable",
         Drop { .. } => "Drop",
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index cc35e6106e2..135889d0da8 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -515,15 +515,15 @@ pub struct CopyNonOverlapping<'tcx> {
 ///
 /// A note on unwinding: Panics may occur during the execution of some terminators. Depending on the
 /// `-C panic` flag, this may either cause the program to abort or the call stack to unwind. Such
-/// terminators have a `cleanup: Option<BasicBlock>` field on them. If stack unwinding occurs, then
-/// once the current function is reached, execution continues at the given basic block, if any. If
-/// `cleanup` is `None` then no cleanup is performed, and the stack continues unwinding. This is
-/// equivalent to the execution of a `Resume` terminator.
+/// terminators have a `unwind: UnwindAction` field on them. If stack unwinding occurs, then
+/// once the current function is reached, an action will be taken based on the `unwind` field.
+/// If the action is `Cleanup`, then the execution continues at the given basic block. If the
+/// action is `Continue` then no cleanup is performed, and the stack continues unwinding.
 ///
-/// The basic block pointed to by a `cleanup` field must have its `cleanup` flag set. `cleanup`
-/// basic blocks have a couple restrictions:
-///  1. All `cleanup` fields in them must be `None`.
-///  2. `Return` terminators are not allowed in them. `Abort` and `Unwind` terminators are.
+/// The basic block pointed to by a `Cleanup` unwind action must have its `cleanup` flag set.
+/// `cleanup` basic blocks have a couple restrictions:
+///  1. All `unwind` fields in them must be `UnwindAction::Terminate` or `UnwindAction::Unreachable`.
+///  2. `Return` terminators are not allowed in them. `Terminate` and `Resume` terminators are.
 ///  3. All other basic blocks (in the current body) that are reachable from `cleanup` basic blocks
 ///     must also be `cleanup`. This is a part of the type system and checked statically, so it is
 ///     still an error to have such an edge in the CFG even if it's known that it won't be taken at
@@ -565,11 +565,11 @@ pub enum TerminatorKind<'tcx> {
     /// deaggregation runs.
     Resume,
 
-    /// Indicates that the landing pad is finished and that the process should abort.
+    /// Indicates that the landing pad is finished and that the process should terminate.
     ///
     /// Used to prevent unwinding for foreign items or with `-C unwind=abort`. Only permitted in
     /// cleanup blocks.
-    Abort,
+    Terminate,
 
     /// Returns from the function.
     ///
@@ -604,7 +604,7 @@ pub enum TerminatorKind<'tcx> {
     /// > The drop glue is executed if, among all statements executed within this `Body`, an assignment to
     /// > the place or one of its "parents" occurred more recently than a move out of it. This does not
     /// > consider indirect assignments.
-    Drop { place: Place<'tcx>, target: BasicBlock, unwind: Option<BasicBlock> },
+    Drop { place: Place<'tcx>, target: BasicBlock, unwind: UnwindAction },
 
     /// Roughly speaking, evaluates the `func` operand and the arguments, and starts execution of
     /// the referred to function. The operand types must match the argument types of the function.
@@ -628,8 +628,8 @@ pub enum TerminatorKind<'tcx> {
         destination: Place<'tcx>,
         /// Where to go after this call returns. If none, the call necessarily diverges.
         target: Option<BasicBlock>,
-        /// Cleanups to be done if the call unwinds.
-        cleanup: Option<BasicBlock>,
+        /// Action to be taken if the call unwinds.
+        unwind: UnwindAction,
         /// `true` if this is from a call in HIR rather than from an overloaded
         /// operator. True for overloaded function call.
         from_hir_call: bool,
@@ -654,7 +654,7 @@ pub enum TerminatorKind<'tcx> {
         expected: bool,
         msg: AssertMessage<'tcx>,
         target: BasicBlock,
-        cleanup: Option<BasicBlock>,
+        unwind: UnwindAction,
     },
 
     /// Marks a suspend point.
@@ -720,9 +720,8 @@ pub enum TerminatorKind<'tcx> {
         /// in practice, but in order to avoid fragility we want to always
         /// consider it in borrowck. We don't want to accept programs which
         /// pass borrowck only when `panic=abort` or some assertions are disabled
-        /// due to release vs. debug mode builds. This needs to be an `Option` because
-        /// of the `remove_noop_landing_pads` and `abort_unwinding_calls` passes.
-        unwind: Option<BasicBlock>,
+        /// due to release vs. debug mode builds.
+        unwind: UnwindAction,
     },
 
     /// Block ends with an inline assembly block. This is a terminator since
@@ -745,12 +744,31 @@ pub enum TerminatorKind<'tcx> {
         /// diverging (InlineAsmOptions::NORETURN).
         destination: Option<BasicBlock>,
 
-        /// Cleanup to be done if the inline assembly unwinds. This is present
+        /// Action to be taken if the inline assembly unwinds. This is present
         /// if and only if InlineAsmOptions::MAY_UNWIND is set.
-        cleanup: Option<BasicBlock>,
+        unwind: UnwindAction,
     },
 }
 
+/// Action to be taken when a stack unwind happens.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
+#[derive(TypeFoldable, TypeVisitable)]
+pub enum UnwindAction {
+    /// No action is to be taken. Continue unwinding.
+    ///
+    /// This is similar to `Cleanup(bb)` where `bb` does nothing but `Resume`, but they are not
+    /// equivalent, as presence of `Cleanup(_)` will make a frame non-POF.
+    Continue,
+    /// Triggers undefined behavior if unwind happens.
+    Unreachable,
+    /// Terminates the execution if unwind happens.
+    ///
+    /// Depending on the platform and situation this may cause a non-unwindable panic or abort.
+    Terminate,
+    /// Cleanups to be done.
+    Cleanup(BasicBlock),
+}
+
 /// Information about an assertion failure.
 #[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)]
 pub enum AssertKind<O> {
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index cd970270727..2c6126cdd29 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -1,6 +1,6 @@
 use smallvec::SmallVec;
 
-use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind};
+use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind, UnwindAction};
 use rustc_ast::InlineAsmTemplatePiece;
 pub use rustc_ast::Mutability;
 use rustc_macros::HashStable;
@@ -118,11 +118,11 @@ impl<'tcx> Terminator<'tcx> {
         self.kind.successors_mut()
     }
 
-    pub fn unwind(&self) -> Option<&Option<BasicBlock>> {
+    pub fn unwind(&self) -> Option<&UnwindAction> {
         self.kind.unwind()
     }
 
-    pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
+    pub fn unwind_mut(&mut self) -> Option<&mut UnwindAction> {
         self.kind.unwind_mut()
     }
 }
@@ -135,33 +135,33 @@ impl<'tcx> TerminatorKind<'tcx> {
     pub fn successors(&self) -> Successors<'_> {
         use self::TerminatorKind::*;
         match *self {
-            Resume
-            | Abort
-            | GeneratorDrop
-            | Return
-            | Unreachable
-            | Call { target: None, cleanup: None, .. }
-            | InlineAsm { destination: None, cleanup: None, .. } => {
-                None.into_iter().chain((&[]).into_iter().copied())
+            Call { target: Some(t), unwind: UnwindAction::Cleanup(ref u), .. }
+            | Yield { resume: t, drop: Some(ref u), .. }
+            | Drop { target: t, unwind: UnwindAction::Cleanup(ref u), .. }
+            | Assert { target: t, unwind: UnwindAction::Cleanup(ref u), .. }
+            | FalseUnwind { real_target: t, unwind: UnwindAction::Cleanup(ref u) }
+            | InlineAsm { destination: Some(t), unwind: UnwindAction::Cleanup(ref u), .. } => {
+                Some(t).into_iter().chain(slice::from_ref(u).into_iter().copied())
             }
             Goto { target: t }
-            | Call { target: None, cleanup: Some(t), .. }
-            | Call { target: Some(t), cleanup: None, .. }
+            | Call { target: None, unwind: UnwindAction::Cleanup(t), .. }
+            | Call { target: Some(t), unwind: _, .. }
             | Yield { resume: t, drop: None, .. }
-            | Drop { target: t, unwind: None, .. }
-            | Assert { target: t, cleanup: None, .. }
-            | FalseUnwind { real_target: t, unwind: None }
-            | InlineAsm { destination: Some(t), cleanup: None, .. }
-            | InlineAsm { destination: None, cleanup: Some(t), .. } => {
+            | Drop { target: t, unwind: _, .. }
+            | Assert { target: t, unwind: _, .. }
+            | FalseUnwind { real_target: t, unwind: _ }
+            | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(t), .. }
+            | InlineAsm { destination: Some(t), unwind: _, .. } => {
                 Some(t).into_iter().chain((&[]).into_iter().copied())
             }
-            Call { target: Some(t), cleanup: Some(ref u), .. }
-            | Yield { resume: t, drop: Some(ref u), .. }
-            | Drop { target: t, unwind: Some(ref u), .. }
-            | Assert { target: t, cleanup: Some(ref u), .. }
-            | FalseUnwind { real_target: t, unwind: Some(ref u) }
-            | InlineAsm { destination: Some(t), cleanup: Some(ref u), .. } => {
-                Some(t).into_iter().chain(slice::from_ref(u).into_iter().copied())
+            Resume
+            | Terminate
+            | GeneratorDrop
+            | Return
+            | Unreachable
+            | Call { target: None, unwind: _, .. }
+            | InlineAsm { destination: None, unwind: _, .. } => {
+                None.into_iter().chain((&[]).into_iter().copied())
             }
             SwitchInt { ref targets, .. } => {
                 None.into_iter().chain(targets.targets.iter().copied())
@@ -175,32 +175,34 @@ impl<'tcx> TerminatorKind<'tcx> {
     pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
         use self::TerminatorKind::*;
         match *self {
-            Resume
-            | Abort
-            | GeneratorDrop
-            | Return
-            | Unreachable
-            | Call { target: None, cleanup: None, .. }
-            | InlineAsm { destination: None, cleanup: None, .. } => None.into_iter().chain(&mut []),
+            Call { target: Some(ref mut t), unwind: UnwindAction::Cleanup(ref mut u), .. }
+            | Yield { resume: ref mut t, drop: Some(ref mut u), .. }
+            | Drop { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. }
+            | Assert { target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u), .. }
+            | FalseUnwind { real_target: ref mut t, unwind: UnwindAction::Cleanup(ref mut u) }
+            | InlineAsm {
+                destination: Some(ref mut t),
+                unwind: UnwindAction::Cleanup(ref mut u),
+                ..
+            } => Some(t).into_iter().chain(slice::from_mut(u)),
             Goto { target: ref mut t }
-            | Call { target: None, cleanup: Some(ref mut t), .. }
-            | Call { target: Some(ref mut t), cleanup: None, .. }
+            | Call { target: None, unwind: UnwindAction::Cleanup(ref mut t), .. }
+            | Call { target: Some(ref mut t), unwind: _, .. }
             | Yield { resume: ref mut t, drop: None, .. }
-            | Drop { target: ref mut t, unwind: None, .. }
-            | Assert { target: ref mut t, cleanup: None, .. }
-            | FalseUnwind { real_target: ref mut t, unwind: None }
-            | InlineAsm { destination: Some(ref mut t), cleanup: None, .. }
-            | InlineAsm { destination: None, cleanup: Some(ref mut t), .. } => {
+            | Drop { target: ref mut t, unwind: _, .. }
+            | Assert { target: ref mut t, unwind: _, .. }
+            | FalseUnwind { real_target: ref mut t, unwind: _ }
+            | InlineAsm { destination: None, unwind: UnwindAction::Cleanup(ref mut t), .. }
+            | InlineAsm { destination: Some(ref mut t), unwind: _, .. } => {
                 Some(t).into_iter().chain(&mut [])
             }
-            Call { target: Some(ref mut t), cleanup: Some(ref mut u), .. }
-            | Yield { resume: ref mut t, drop: Some(ref mut u), .. }
-            | Drop { target: ref mut t, unwind: Some(ref mut u), .. }
-            | Assert { target: ref mut t, cleanup: Some(ref mut u), .. }
-            | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) }
-            | InlineAsm { destination: Some(ref mut t), cleanup: Some(ref mut u), .. } => {
-                Some(t).into_iter().chain(slice::from_mut(u))
-            }
+            Resume
+            | Terminate
+            | GeneratorDrop
+            | Return
+            | Unreachable
+            | Call { target: None, unwind: _, .. }
+            | InlineAsm { destination: None, unwind: _, .. } => None.into_iter().chain(&mut []),
             SwitchInt { ref mut targets, .. } => None.into_iter().chain(&mut targets.targets),
             FalseEdge { ref mut real_target, ref mut imaginary_target } => {
                 Some(real_target).into_iter().chain(slice::from_mut(imaginary_target))
@@ -208,41 +210,41 @@ impl<'tcx> TerminatorKind<'tcx> {
         }
     }
 
-    pub fn unwind(&self) -> Option<&Option<BasicBlock>> {
+    pub fn unwind(&self) -> Option<&UnwindAction> {
         match *self {
             TerminatorKind::Goto { .. }
             | TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Yield { .. }
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::FalseEdge { .. } => None,
-            TerminatorKind::Call { cleanup: ref unwind, .. }
-            | TerminatorKind::Assert { cleanup: ref unwind, .. }
+            TerminatorKind::Call { ref unwind, .. }
+            | TerminatorKind::Assert { ref unwind, .. }
             | TerminatorKind::Drop { ref unwind, .. }
             | TerminatorKind::FalseUnwind { ref unwind, .. }
-            | TerminatorKind::InlineAsm { cleanup: ref unwind, .. } => Some(unwind),
+            | TerminatorKind::InlineAsm { ref unwind, .. } => Some(unwind),
         }
     }
 
-    pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> {
+    pub fn unwind_mut(&mut self) -> Option<&mut UnwindAction> {
         match *self {
             TerminatorKind::Goto { .. }
             | TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Yield { .. }
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::FalseEdge { .. } => None,
-            TerminatorKind::Call { cleanup: ref mut unwind, .. }
-            | TerminatorKind::Assert { cleanup: ref mut unwind, .. }
+            TerminatorKind::Call { ref mut unwind, .. }
+            | TerminatorKind::Assert { ref mut unwind, .. }
             | TerminatorKind::Drop { ref mut unwind, .. }
             | TerminatorKind::FalseUnwind { ref mut unwind, .. }
-            | TerminatorKind::InlineAsm { cleanup: ref mut unwind, .. } => Some(unwind),
+            | TerminatorKind::InlineAsm { ref mut unwind, .. } => Some(unwind),
         }
     }
 
@@ -268,11 +270,17 @@ impl<'tcx> Debug for TerminatorKind<'tcx> {
         let labels = self.fmt_successor_labels();
         assert_eq!(successor_count, labels.len());
 
-        match successor_count {
-            0 => Ok(()),
-
-            1 => write!(fmt, " -> {:?}", self.successors().next().unwrap()),
-
+        let unwind = match self.unwind() {
+            // Not needed or included in successors
+            None | Some(UnwindAction::Continue) | Some(UnwindAction::Cleanup(_)) => None,
+            Some(UnwindAction::Unreachable) => Some("unwind unreachable"),
+            Some(UnwindAction::Terminate) => Some("unwind terminate"),
+        };
+
+        match (successor_count, unwind) {
+            (0, None) => Ok(()),
+            (0, Some(unwind)) => write!(fmt, " -> {}", unwind),
+            (1, None) => write!(fmt, " -> {:?}", self.successors().next().unwrap()),
             _ => {
                 write!(fmt, " -> [")?;
                 for (i, target) in self.successors().enumerate() {
@@ -281,6 +289,9 @@ impl<'tcx> Debug for TerminatorKind<'tcx> {
                     }
                     write!(fmt, "{}: {:?}", labels[i], target)?;
                 }
+                if let Some(unwind) = unwind {
+                    write!(fmt, ", {unwind}")?;
+                }
                 write!(fmt, "]")
             }
         }
@@ -299,7 +310,7 @@ impl<'tcx> TerminatorKind<'tcx> {
             Return => write!(fmt, "return"),
             GeneratorDrop => write!(fmt, "generator_drop"),
             Resume => write!(fmt, "resume"),
-            Abort => write!(fmt, "abort"),
+            Terminate => write!(fmt, "abort"),
             Yield { value, resume_arg, .. } => write!(fmt, "{:?} = yield({:?})", resume_arg, value),
             Unreachable => write!(fmt, "unreachable"),
             Drop { place, .. } => write!(fmt, "drop({:?})", place),
@@ -378,7 +389,7 @@ impl<'tcx> TerminatorKind<'tcx> {
     pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
         use self::TerminatorKind::*;
         match *self {
-            Return | Resume | Abort | Unreachable | GeneratorDrop => vec![],
+            Return | Resume | Terminate | Unreachable | GeneratorDrop => vec![],
             Goto { .. } => vec!["".into()],
             SwitchInt { ref targets, .. } => targets
                 .values
@@ -386,31 +397,35 @@ impl<'tcx> TerminatorKind<'tcx> {
                 .map(|&u| Cow::Owned(u.to_string()))
                 .chain(iter::once("otherwise".into()))
                 .collect(),
-            Call { target: Some(_), cleanup: Some(_), .. } => {
+            Call { target: Some(_), unwind: UnwindAction::Cleanup(_), .. } => {
                 vec!["return".into(), "unwind".into()]
             }
-            Call { target: Some(_), cleanup: None, .. } => vec!["return".into()],
-            Call { target: None, cleanup: Some(_), .. } => vec!["unwind".into()],
-            Call { target: None, cleanup: None, .. } => vec![],
+            Call { target: Some(_), unwind: _, .. } => vec!["return".into()],
+            Call { target: None, unwind: UnwindAction::Cleanup(_), .. } => vec!["unwind".into()],
+            Call { target: None, unwind: _, .. } => vec![],
             Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()],
             Yield { drop: None, .. } => vec!["resume".into()],
-            Drop { unwind: None, .. } => {
-                vec!["return".into()]
-            }
-            Drop { unwind: Some(_), .. } => {
-                vec!["return".into(), "unwind".into()]
+            Drop { unwind: UnwindAction::Cleanup(_), .. } => vec!["return".into(), "unwind".into()],
+            Drop { unwind: _, .. } => vec!["return".into()],
+            Assert { unwind: UnwindAction::Cleanup(_), .. } => {
+                vec!["success".into(), "unwind".into()]
             }
-            Assert { cleanup: None, .. } => vec!["".into()],
-            Assert { .. } => vec!["success".into(), "unwind".into()],
+            Assert { unwind: _, .. } => vec!["success".into()],
             FalseEdge { .. } => vec!["real".into(), "imaginary".into()],
-            FalseUnwind { unwind: Some(_), .. } => vec!["real".into(), "cleanup".into()],
-            FalseUnwind { unwind: None, .. } => vec!["real".into()],
-            InlineAsm { destination: Some(_), cleanup: Some(_), .. } => {
+            FalseUnwind { unwind: UnwindAction::Cleanup(_), .. } => {
+                vec!["real".into(), "unwind".into()]
+            }
+            FalseUnwind { unwind: _, .. } => vec!["real".into()],
+            InlineAsm { destination: Some(_), unwind: UnwindAction::Cleanup(_), .. } => {
                 vec!["return".into(), "unwind".into()]
             }
-            InlineAsm { destination: Some(_), cleanup: None, .. } => vec!["return".into()],
-            InlineAsm { destination: None, cleanup: Some(_), .. } => vec!["unwind".into()],
-            InlineAsm { destination: None, cleanup: None, .. } => vec![],
+            InlineAsm { destination: Some(_), unwind: _, .. } => {
+                vec!["return".into()]
+            }
+            InlineAsm { destination: None, unwind: UnwindAction::Cleanup(_), .. } => {
+                vec!["unwind".into()]
+            }
+            InlineAsm { destination: None, unwind: _, .. } => vec![],
         }
     }
 }
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 7aa446ae966..6c4ea065abe 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -462,7 +462,7 @@ macro_rules! make_mir_visitor {
                 match kind {
                     TerminatorKind::Goto { .. } |
                     TerminatorKind::Resume |
-                    TerminatorKind::Abort |
+                    TerminatorKind::Terminate |
                     TerminatorKind::GeneratorDrop |
                     TerminatorKind::Unreachable |
                     TerminatorKind::FalseEdge { .. } |
@@ -509,7 +509,7 @@ macro_rules! make_mir_visitor {
                         args,
                         destination,
                         target: _,
-                        cleanup: _,
+                        unwind: _,
                         from_hir_call: _,
                         fn_span: _
                     } => {
@@ -529,7 +529,7 @@ macro_rules! make_mir_visitor {
                         expected: _,
                         msg,
                         target: _,
-                        cleanup: _,
+                        unwind: _,
                     } => {
                         self.visit_operand(cond, location);
                         self.visit_assert_message(msg, location);
@@ -555,7 +555,7 @@ macro_rules! make_mir_visitor {
                         options: _,
                         line_spans: _,
                         destination: _,
-                        cleanup: _,
+                        unwind: _,
                     } => {
                         for op in operands {
                             match op {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 8d0aa622244..299b1bf1d96 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -311,7 +311,7 @@ pub struct CommonLifetimes<'tcx> {
     pub re_vars: Vec<Region<'tcx>>,
 
     /// Pre-interned values of the form:
-    /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(v, None) })`
+    /// `ReLateBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon(None) })`
     /// for small values of `i` and `v`.
     pub re_late_bounds: Vec<Vec<Region<'tcx>>>,
 }
@@ -386,10 +386,7 @@ impl<'tcx> CommonLifetimes<'tcx> {
                     .map(|v| {
                         mk(ty::ReLateBound(
                             ty::DebruijnIndex::from(i),
-                            ty::BoundRegion {
-                                var: ty::BoundVar::from(v),
-                                kind: ty::BrAnon(v, None),
-                            },
+                            ty::BoundRegion { var: ty::BoundVar::from(v), kind: ty::BrAnon(None) },
                         ))
                     })
                     .collect()
@@ -2075,10 +2072,9 @@ impl<'tcx> TyCtxt<'tcx> {
         bound_region: ty::BoundRegion,
     ) -> Region<'tcx> {
         // Use a pre-interned one when possible.
-        if let ty::BoundRegion { var, kind: ty::BrAnon(v, None) } = bound_region
-            && var.as_u32() == v
+        if let ty::BoundRegion { var, kind: ty::BrAnon(None) } = bound_region
             && let Some(inner) = self.lifetimes.re_late_bounds.get(debruijn.as_usize())
-            && let Some(re) = inner.get(v as usize).copied()
+            && let Some(re) = inner.get(var.as_usize()).copied()
         {
             re
         } else {
diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs
index 6205e2bf24d..203e16bea27 100644
--- a/compiler/rustc_middle/src/ty/fold.rs
+++ b/compiler/rustc_middle/src/ty/fold.rs
@@ -379,9 +379,7 @@ impl<'tcx> TyCtxt<'tcx> {
                 let index = entry.index();
                 let var = ty::BoundVar::from_usize(index);
                 let kind = entry
-                    .or_insert_with(|| {
-                        ty::BoundVariableKind::Region(ty::BrAnon(index as u32, None))
-                    })
+                    .or_insert_with(|| ty::BoundVariableKind::Region(ty::BrAnon(None)))
                     .expect_region();
                 let br = ty::BoundRegion { var, kind };
                 self.tcx.mk_re_late_bound(ty::INNERMOST, br)
@@ -391,9 +389,7 @@ impl<'tcx> TyCtxt<'tcx> {
                 let index = entry.index();
                 let var = ty::BoundVar::from_usize(index);
                 let kind = entry
-                    .or_insert_with(|| {
-                        ty::BoundVariableKind::Ty(ty::BoundTyKind::Anon(index as u32))
-                    })
+                    .or_insert_with(|| ty::BoundVariableKind::Ty(ty::BoundTyKind::Anon))
                     .expect_ty();
                 self.tcx.mk_bound(ty::INNERMOST, BoundTy { var, kind })
             }
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 8af9acfadde..2328a1324fc 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -281,6 +281,12 @@ pub enum SizeSkeleton<'tcx> {
     /// Any statically computable Layout.
     Known(Size),
 
+    /// This is a generic const expression (i.e. N * 2), which may contain some parameters.
+    /// It must be of type usize, and represents the size of a type in bytes.
+    /// It is not required to be evaluatable to a concrete value, but can be used to check
+    /// that another SizeSkeleton is of equal size.
+    Generic(ty::Const<'tcx>),
+
     /// A potentially-fat pointer.
     Pointer {
         /// If true, this pointer is never null.
@@ -326,6 +332,37 @@ impl<'tcx> SizeSkeleton<'tcx> {
                     ),
                 }
             }
+            ty::Array(inner, len)
+                if len.ty() == tcx.types.usize && tcx.features().transmute_generic_consts =>
+            {
+                match SizeSkeleton::compute(inner, tcx, param_env)? {
+                    // This may succeed because the multiplication of two types may overflow
+                    // but a single size of a nested array will not.
+                    SizeSkeleton::Known(s) => {
+                        if let Some(c) = len.try_eval_target_usize(tcx, param_env) {
+                            let size = s
+                                .bytes()
+                                .checked_mul(c)
+                                .ok_or_else(|| LayoutError::SizeOverflow(ty))?;
+                            return Ok(SizeSkeleton::Known(Size::from_bytes(size)));
+                        }
+                        let len = tcx.expand_abstract_consts(len);
+                        let prev = ty::Const::from_target_usize(tcx, s.bytes());
+                        let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, prev) else {
+                            return Err(LayoutError::SizeOverflow(ty));
+                        };
+                        Ok(SizeSkeleton::Generic(gen_size))
+                    }
+                    SizeSkeleton::Pointer { .. } => Err(err),
+                    SizeSkeleton::Generic(g) => {
+                        let len = tcx.expand_abstract_consts(len);
+                        let Some(gen_size) = mul_sorted_consts(tcx, param_env, len, g) else {
+                            return Err(LayoutError::SizeOverflow(ty));
+                        };
+                        Ok(SizeSkeleton::Generic(gen_size))
+                    }
+                }
+            }
 
             ty::Adt(def, substs) => {
                 // Only newtypes and enums w/ nullable pointer optimization.
@@ -355,6 +392,9 @@ impl<'tcx> SizeSkeleton<'tcx> {
                                 }
                                 ptr = Some(field);
                             }
+                            SizeSkeleton::Generic(_) => {
+                                return Err(err);
+                            }
                         }
                     }
                     Ok(ptr)
@@ -410,11 +450,66 @@ impl<'tcx> SizeSkeleton<'tcx> {
             (SizeSkeleton::Pointer { tail: a, .. }, SizeSkeleton::Pointer { tail: b, .. }) => {
                 a == b
             }
+            // constants are always pre-normalized into a canonical form so this
+            // only needs to check if their pointers are identical.
+            (SizeSkeleton::Generic(a), SizeSkeleton::Generic(b)) => a == b,
             _ => false,
         }
     }
 }
 
+/// When creating the layout for types with abstract conts in their size (i.e. [usize; 4 * N]),
+/// to ensure that they have a canonical order and can be compared directly we combine all
+/// constants, and sort the other terms. This allows comparison of expressions of sizes,
+/// allowing for things like transmutating between types that depend on generic consts.
+/// This returns `None` if multiplication of constants overflows.
+fn mul_sorted_consts<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+    a: ty::Const<'tcx>,
+    b: ty::Const<'tcx>,
+) -> Option<ty::Const<'tcx>> {
+    use crate::mir::BinOp::Mul;
+    use ty::ConstKind::Expr;
+    use ty::Expr::Binop;
+
+    let mut work = vec![a, b];
+    let mut done = vec![];
+    while let Some(n) = work.pop() {
+        if let Expr(Binop(Mul, l, r)) = n.kind() {
+            work.push(l);
+            work.push(r)
+        } else {
+            done.push(n);
+        }
+    }
+    let mut k = 1;
+    let mut overflow = false;
+    done.retain(|c| {
+        let Some(c) = c.try_eval_target_usize(tcx, param_env) else {
+            return true;
+        };
+        let Some(next) = c.checked_mul(k) else {
+            overflow = true;
+            return false;
+        };
+        k = next;
+        false
+    });
+    if overflow {
+        return None;
+    }
+    if k != 1 {
+        done.push(ty::Const::from_target_usize(tcx, k));
+    } else if k == 0 {
+        return Some(ty::Const::from_target_usize(tcx, 0));
+    }
+    done.sort_unstable();
+
+    // create a single tree from the buffer
+    done.into_iter().reduce(|acc, n| tcx.mk_const(Expr(Binop(Mul, n, acc)), n.ty()))
+}
+
 pub trait HasTyCtxt<'tcx>: HasDataLayout {
     fn tcx(&self) -> TyCtxt<'tcx>;
 }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 800a230b654..c856bb25e14 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1454,12 +1454,12 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
 #[derive(HashStable, TyEncodable, TyDecodable)]
 pub struct Placeholder<T> {
     pub universe: UniverseIndex,
-    pub name: T,
+    pub bound: T,
 }
 
-pub type PlaceholderRegion = Placeholder<BoundRegionKind>;
+pub type PlaceholderRegion = Placeholder<BoundRegion>;
 
-pub type PlaceholderType = Placeholder<BoundTyKind>;
+pub type PlaceholderType = Placeholder<BoundTy>;
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
 #[derive(TyEncodable, TyDecodable, PartialOrd, Ord)]
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index de4c703107e..bc0ccc1ebc3 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -701,9 +701,7 @@ pub trait PrettyPrinter<'tcx>:
             ty::Error(_) => p!("[type error]"),
             ty::Param(ref param_ty) => p!(print(param_ty)),
             ty::Bound(debruijn, bound_ty) => match bound_ty.kind {
-                ty::BoundTyKind::Anon(bv) => {
-                    self.pretty_print_bound_var(debruijn, ty::BoundVar::from_u32(bv))?
-                }
+                ty::BoundTyKind::Anon => self.pretty_print_bound_var(debruijn, bound_ty.var)?,
                 ty::BoundTyKind::Param(_, s) => match self.should_print_verbose() {
                     true if debruijn == ty::INNERMOST => p!(write("^{}", s)),
                     true => p!(write("^{}_{}", debruijn.index(), s)),
@@ -739,8 +737,8 @@ pub trait PrettyPrinter<'tcx>:
                     p!(print(data))
                 }
             }
-            ty::Placeholder(placeholder) => match placeholder.name {
-                ty::BoundTyKind::Anon(_) => p!(write("Placeholder({:?})", placeholder)),
+            ty::Placeholder(placeholder) => match placeholder.bound.kind {
+                ty::BoundTyKind::Anon => p!(write("Placeholder({:?})", placeholder)),
                 ty::BoundTyKind::Param(_, name) => p!(write("{}", name)),
             },
             ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
@@ -2104,7 +2102,9 @@ impl<'tcx> PrettyPrinter<'tcx> for FmtPrinter<'_, 'tcx> {
 
             ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
             | ty::ReFree(ty::FreeRegion { bound_region: br, .. })
-            | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
+            | ty::RePlaceholder(ty::Placeholder {
+                bound: ty::BoundRegion { kind: br, .. }, ..
+            }) => {
                 if br.is_named() {
                     return true;
                 }
@@ -2181,7 +2181,9 @@ impl<'tcx> FmtPrinter<'_, 'tcx> {
             }
             ty::ReLateBound(_, ty::BoundRegion { kind: br, .. })
             | ty::ReFree(ty::FreeRegion { bound_region: br, .. })
-            | ty::RePlaceholder(ty::Placeholder { name: br, .. }) => {
+            | ty::RePlaceholder(ty::Placeholder {
+                bound: ty::BoundRegion { kind: br, .. }, ..
+            }) => {
                 if let ty::BrNamed(_, name) = br && br.is_named() {
                     p!(write("{}", name));
                     return Ok(self);
@@ -2259,7 +2261,10 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
             ty::ReLateBound(db, br) if db >= self.current_index => {
                 *self.region_map.entry(br).or_insert_with(|| name(Some(db), self.current_index, br))
             }
-            ty::RePlaceholder(ty::PlaceholderRegion { name: kind, .. }) => {
+            ty::RePlaceholder(ty::PlaceholderRegion {
+                bound: ty::BoundRegion { kind, .. },
+                ..
+            }) => {
                 // If this is an anonymous placeholder, don't rename. Otherwise, in some
                 // async fns, we get a `for<'r> Send` bound
                 match kind {
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index d4f058440b9..5c604bb6db2 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -68,7 +68,7 @@ impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> {
 impl fmt::Debug for ty::BoundRegionKind {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
-            ty::BrAnon(n, span) => write!(f, "BrAnon({n:?}, {span:?})"),
+            ty::BrAnon(span) => write!(f, "BrAnon({span:?})"),
             ty::BrNamed(did, name) => {
                 if did.is_crate_root() {
                     write!(f, "BrNamed({})", name)
@@ -254,8 +254,8 @@ TrivialTypeTraversalAndLiftImpls! {
     crate::ty::AssocKind,
     crate::ty::AliasKind,
     crate::ty::AliasRelationDirection,
-    crate::ty::Placeholder<crate::ty::BoundRegionKind>,
-    crate::ty::Placeholder<crate::ty::BoundTyKind>,
+    crate::ty::Placeholder<crate::ty::BoundRegion>,
+    crate::ty::Placeholder<crate::ty::BoundTy>,
     crate::ty::ClosureKind,
     crate::ty::FreeRegion,
     crate::ty::InferTy,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 5ea77833af2..0e2e2a956ec 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -60,7 +60,7 @@ pub struct FreeRegion {
 #[derive(HashStable)]
 pub enum BoundRegionKind {
     /// An anonymous region parameter for a given fn (&T)
-    BrAnon(u32, Option<Span>),
+    BrAnon(Option<Span>),
 
     /// Named region parameters for functions (a in &'a T)
     ///
@@ -107,15 +107,6 @@ impl BoundRegionKind {
             _ => None,
         }
     }
-
-    pub fn expect_anon(&self) -> u32 {
-        match *self {
-            BoundRegionKind::BrNamed(_, _) | BoundRegionKind::BrEnv => {
-                bug!("expected anon region: {self:?}")
-            }
-            BoundRegionKind::BrAnon(idx, _) => idx,
-        }
-    }
 }
 
 pub trait Article {
@@ -136,10 +127,6 @@ impl<'tcx> Article for TyKind<'tcx> {
     }
 }
 
-// `TyKind` is used a lot. Make sure it doesn't unintentionally get bigger.
-#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
-static_assert_size!(TyKind<'_>, 32);
-
 /// A closure can be modeled as a struct that looks like:
 /// ```ignore (illustrative)
 /// struct Closure<'l0...'li, T0...Tj, CK, CS, U>(...U);
@@ -1533,22 +1520,13 @@ pub struct BoundTy {
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
 #[derive(HashStable)]
 pub enum BoundTyKind {
-    Anon(u32),
+    Anon,
     Param(DefId, Symbol),
 }
 
-impl BoundTyKind {
-    pub fn expect_anon(self) -> u32 {
-        match self {
-            BoundTyKind::Anon(i) => i,
-            _ => bug!(),
-        }
-    }
-}
-
 impl From<BoundVar> for BoundTy {
     fn from(var: BoundVar) -> Self {
-        BoundTy { var, kind: BoundTyKind::Anon(var.as_u32()) }
+        BoundTy { var, kind: BoundTyKind::Anon }
     }
 }
 
@@ -1632,7 +1610,7 @@ impl<'tcx> Region<'tcx> {
                 ty::ReLateBound(_, br) => br.kind.get_name(),
                 ty::ReFree(fr) => fr.bound_region.get_name(),
                 ty::ReStatic => Some(kw::StaticLifetime),
-                ty::RePlaceholder(placeholder) => placeholder.name.get_name(),
+                ty::RePlaceholder(placeholder) => placeholder.bound.kind.get_name(),
                 _ => None,
             };
 
@@ -1650,7 +1628,7 @@ impl<'tcx> Region<'tcx> {
             ty::ReFree(fr) => fr.bound_region.is_named(),
             ty::ReStatic => true,
             ty::ReVar(..) => false,
-            ty::RePlaceholder(placeholder) => placeholder.name.is_named(),
+            ty::RePlaceholder(placeholder) => placeholder.bound.kind.is_named(),
             ty::ReErased => false,
             ty::ReError(_) => false,
         }
@@ -2514,3 +2492,14 @@ impl<'tcx> VarianceDiagInfo<'tcx> {
         }
     }
 }
+
+// Some types are used a lot. Make sure they don't unintentionally get bigger.
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+mod size_asserts {
+    use super::*;
+    use rustc_data_structures::static_assert_size;
+    // tidy-alphabetical-start
+    static_assert_size!(RegionKind<'_>, 28);
+    static_assert_size!(TyKind<'_>, 32);
+    // tidy-alphabetical-end
+}
diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
index 33b73928704..54028dfe87b 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -56,7 +56,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
                 Ok(TerminatorKind::Drop {
                     place: self.parse_place(args[0])?,
                     target: self.parse_block(args[1])?,
-                    unwind: None,
+                    unwind: UnwindAction::Continue,
                 })
             },
             @call("mir_call", args) => {
@@ -126,7 +126,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
                     args,
                     destination,
                     target: Some(target),
-                    cleanup: None,
+                    unwind: UnwindAction::Continue,
                     from_hir_call: *from_hir_call,
                     fn_span: *fn_span,
                 })
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index baa12ec11c3..8631749a524 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -171,7 +171,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         args: vec![Operand::Move(size), Operand::Move(align)],
                         destination: storage,
                         target: Some(success),
-                        cleanup: None,
+                        unwind: UnwindAction::Continue,
                         from_hir_call: false,
                         fn_span: expr_span,
                     },
@@ -702,7 +702,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 this.cfg.terminate(
                     block,
                     outer_source_info,
-                    TerminatorKind::Drop { place: to_drop, target: success, unwind: None },
+                    TerminatorKind::Drop {
+                        place: to_drop,
+                        target: success,
+                        unwind: UnwindAction::Continue,
+                    },
                 );
                 this.diverge_from(block);
                 block = success;
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 8efaba1f602..05a723a6b67 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -228,7 +228,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     this.cfg.terminate(
                         loop_block,
                         source_info,
-                        TerminatorKind::FalseUnwind { real_target: body_block, unwind: None },
+                        TerminatorKind::FalseUnwind {
+                            real_target: body_block,
+                            unwind: UnwindAction::Continue,
+                        },
                     );
                     this.diverge_from(loop_block);
 
@@ -264,7 +267,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     TerminatorKind::Call {
                         func: fun,
                         args,
-                        cleanup: None,
+                        unwind: UnwindAction::Continue,
                         destination,
                         // The presence or absence of a return edge affects control-flow sensitive
                         // MIR checks and ultimately whether code is accepted or not. We can only
@@ -466,7 +469,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         } else {
                             Some(destination_block)
                         },
-                        cleanup: None,
+                        unwind: if options.contains(InlineAsmOptions::MAY_UNWIND) {
+                            UnwindAction::Continue
+                        } else {
+                            UnwindAction::Unreachable
+                        },
                     },
                 );
                 if options.contains(InlineAsmOptions::MAY_UNWIND) {
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 2de89f67dfd..8a03ea7e2cc 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -263,7 +263,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                             args: vec![Operand::Move(ref_string)],
                             destination: ref_str,
                             target: Some(eq_block),
-                            cleanup: None,
+                            unwind: UnwindAction::Continue,
                             from_hir_call: false,
                             fn_span: source_info.span
                         }
@@ -466,7 +466,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 args: vec![val, expect],
                 destination: eq_result,
                 target: Some(eq_block),
-                cleanup: None,
+                unwind: UnwindAction::Continue,
                 from_hir_call: false,
                 fn_span: source_info.span,
             },
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 25af221bf36..f32d2db4e71 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -369,7 +369,7 @@ impl DropTree {
                     let terminator = TerminatorKind::Drop {
                         target: blocks[drop_data.1].unwrap(),
                         // The caller will handle this if needed.
-                        unwind: None,
+                        unwind: UnwindAction::Terminate,
                         place: drop_data.0.local.into(),
                     };
                     cfg.terminate(block, drop_data.0.source_info, terminator);
@@ -1141,7 +1141,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         self.cfg.terminate(
             block,
             source_info,
-            TerminatorKind::Drop { place, target: assign, unwind: Some(assign_unwind) },
+            TerminatorKind::Drop {
+                place,
+                target: assign,
+                unwind: UnwindAction::Cleanup(assign_unwind),
+            },
         );
         self.diverge_from(block);
 
@@ -1165,7 +1169,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         self.cfg.terminate(
             block,
             source_info,
-            TerminatorKind::Assert { cond, expected, msg, target: success_block, cleanup: None },
+            TerminatorKind::Assert {
+                cond,
+                expected,
+                msg,
+                target: success_block,
+                unwind: UnwindAction::Continue,
+            },
         );
         self.diverge_from(block);
 
@@ -1244,7 +1254,11 @@ fn build_scope_drops<'tcx>(
                 cfg.terminate(
                     block,
                     source_info,
-                    TerminatorKind::Drop { place: local.into(), target: next, unwind: None },
+                    TerminatorKind::Drop {
+                        place: local.into(),
+                        target: next,
+                        unwind: UnwindAction::Continue,
+                    },
                 );
                 block = next;
             }
@@ -1424,23 +1438,23 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind {
         let term = &mut cfg.block_data_mut(from).terminator_mut();
         match &mut term.kind {
             TerminatorKind::Drop { unwind, .. } => {
-                if let Some(unwind) = *unwind {
+                if let UnwindAction::Cleanup(unwind) = *unwind {
                     let source_info = term.source_info;
                     cfg.terminate(unwind, source_info, TerminatorKind::Goto { target: to });
                 } else {
-                    *unwind = Some(to);
+                    *unwind = UnwindAction::Cleanup(to);
                 }
             }
             TerminatorKind::FalseUnwind { unwind, .. }
-            | TerminatorKind::Call { cleanup: unwind, .. }
-            | TerminatorKind::Assert { cleanup: unwind, .. }
-            | TerminatorKind::InlineAsm { cleanup: unwind, .. } => {
-                *unwind = Some(to);
+            | TerminatorKind::Call { unwind, .. }
+            | TerminatorKind::Assert { unwind, .. }
+            | TerminatorKind::InlineAsm { unwind, .. } => {
+                *unwind = UnwindAction::Cleanup(to);
             }
             TerminatorKind::Goto { .. }
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::Yield { .. }
diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs
index 8937b78fe34..8e41957af0e 100644
--- a/compiler/rustc_mir_build/src/lints.rs
+++ b/compiler/rustc_mir_build/src/lints.rs
@@ -3,7 +3,7 @@ use rustc_data_structures::graph::iterate::{
     NodeStatus, TriColorDepthFirstSearch, TriColorVisitor,
 };
 use rustc_hir::def::DefKind;
-use rustc_middle::mir::{BasicBlock, BasicBlocks, Body, Operand, TerminatorKind};
+use rustc_middle::mir::{self, BasicBlock, BasicBlocks, Body, Operand, TerminatorKind};
 use rustc_middle::ty::subst::{GenericArg, InternalSubsts};
 use rustc_middle::ty::{self, Instance, TyCtxt};
 use rustc_session::lint::builtin::UNCONDITIONAL_RECURSION;
@@ -108,7 +108,7 @@ impl<'mir, 'tcx> TriColorVisitor<BasicBlocks<'tcx>> for Search<'mir, 'tcx> {
 
         match self.body[bb].terminator().kind {
             // These terminators return control flow to the caller.
-            TerminatorKind::Abort
+            TerminatorKind::Terminate
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Resume
             | TerminatorKind::Return
@@ -149,7 +149,9 @@ impl<'mir, 'tcx> TriColorVisitor<BasicBlocks<'tcx>> for Search<'mir, 'tcx> {
 
     fn ignore_edge(&mut self, bb: BasicBlock, target: BasicBlock) -> bool {
         let terminator = self.body[bb].terminator();
-        if terminator.unwind() == Some(&Some(target)) && terminator.successors().count() > 1 {
+        if terminator.unwind() == Some(&mir::UnwindAction::Cleanup(target))
+            && terminator.successors().count() > 1
+        {
             return true;
         }
         // Don't traverse successors of recursive calls or false CFG edges.
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index 7ef3d41ac48..bd8ec82dffd 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -77,10 +77,10 @@ impl Unwind {
         }
     }
 
-    fn into_option(self) -> Option<BasicBlock> {
+    fn into_action(self) -> UnwindAction {
         match self {
-            Unwind::To(bb) => Some(bb),
-            Unwind::InCleanup => None,
+            Unwind::To(bb) => UnwindAction::Cleanup(bb),
+            Unwind::InCleanup => UnwindAction::Terminate,
         }
     }
 
@@ -236,7 +236,7 @@ where
                     TerminatorKind::Drop {
                         place: self.place,
                         target: self.succ,
-                        unwind: self.unwind.into_option(),
+                        unwind: self.unwind.into_action(),
                     },
                 );
             }
@@ -640,7 +640,7 @@ where
                     args: vec![Operand::Move(Place::from(ref_place))],
                     destination: unit_temp,
                     target: Some(succ),
-                    cleanup: unwind.into_option(),
+                    unwind: unwind.into_action(),
                     from_hir_call: true,
                     fn_span: self.source_info.span,
                 },
@@ -717,7 +717,7 @@ where
             TerminatorKind::Drop {
                 place: tcx.mk_place_deref(ptr),
                 target: loop_block,
-                unwind: unwind.into_option(),
+                unwind: unwind.into_action(),
             },
         );
 
@@ -946,7 +946,11 @@ where
             args,
             destination: unit_temp,
             target: Some(target),
-            cleanup: None,
+            unwind: if unwind.is_cleanup() {
+                UnwindAction::Terminate
+            } else {
+                UnwindAction::Continue
+            },
             from_hir_call: false,
             fn_span: self.source_info.span,
         }; // FIXME(#43234)
@@ -959,7 +963,7 @@ where
 
     fn drop_block(&mut self, target: BasicBlock, unwind: Unwind) -> BasicBlock {
         let block =
-            TerminatorKind::Drop { place: self.place, target, unwind: unwind.into_option() };
+            TerminatorKind::Drop { place: self.place, target, unwind: unwind.into_action() };
         self.new_block(unwind, block)
     }
 
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index a40c38aa4c3..c8fe1af6674 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -1,4 +1,4 @@
-use rustc_middle::mir::{self, BasicBlock, Location, SwitchTargets};
+use rustc_middle::mir::{self, BasicBlock, Location, SwitchTargets, UnwindAction};
 use rustc_middle::ty::TyCtxt;
 use std::ops::RangeInclusive;
 
@@ -474,14 +474,14 @@ impl Direction for Forward {
     {
         use mir::TerminatorKind::*;
         match bb_data.terminator().kind {
-            Return | Resume | Abort | GeneratorDrop | Unreachable => {}
+            Return | Resume | Terminate | GeneratorDrop | Unreachable => {}
 
             Goto { target } => propagate(target, exit_state),
 
-            Assert { target, cleanup: unwind, expected: _, msg: _, cond: _ }
+            Assert { target, unwind, expected: _, msg: _, cond: _ }
             | Drop { target, unwind, place: _ }
             | FalseUnwind { real_target: target, unwind } => {
-                if let Some(unwind) = unwind {
+                if let UnwindAction::Cleanup(unwind) = unwind {
                     propagate(unwind, exit_state);
                 }
 
@@ -503,7 +503,7 @@ impl Direction for Forward {
             }
 
             Call {
-                cleanup,
+                unwind,
                 destination,
                 target,
                 func: _,
@@ -511,7 +511,7 @@ impl Direction for Forward {
                 from_hir_call: _,
                 fn_span: _,
             } => {
-                if let Some(unwind) = cleanup {
+                if let UnwindAction::Cleanup(unwind) = unwind {
                     propagate(unwind, exit_state);
                 }
 
@@ -533,9 +533,9 @@ impl Direction for Forward {
                 options: _,
                 line_spans: _,
                 destination,
-                cleanup,
+                unwind,
             } => {
-                if let Some(unwind) = cleanup {
+                if let UnwindAction::Cleanup(unwind) = unwind {
                     propagate(unwind, exit_state);
                 }
 
diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs
index 17102454a88..60679b17d6c 100644
--- a/compiler/rustc_mir_dataflow/src/framework/tests.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs
@@ -39,7 +39,7 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> {
             args: vec![],
             destination: dummy_place.clone(),
             target: Some(mir::START_BLOCK),
-            cleanup: None,
+            unwind: mir::UnwindAction::Continue,
             from_hir_call: false,
             fn_span: DUMMY_SP,
         },
@@ -53,7 +53,7 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> {
             args: vec![],
             destination: dummy_place.clone(),
             target: Some(mir::START_BLOCK),
-            cleanup: None,
+            unwind: mir::UnwindAction::Continue,
             from_hir_call: false,
             fn_span: DUMMY_SP,
         },
diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
index 08fadfe68a1..92d30f254a6 100644
--- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
@@ -125,7 +125,7 @@ where
                 }
             }
 
-            TerminatorKind::Abort
+            TerminatorKind::Terminate
             | TerminatorKind::Assert { .. }
             | TerminatorKind::Call { .. }
             | TerminatorKind::FalseEdge { .. }
diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
index 99988b29e8a..4a5d9d52010 100644
--- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
@@ -200,7 +200,7 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc
 
             // Nothing to do for these. Match exhaustively so this fails to compile when new
             // variants are added.
-            TerminatorKind::Abort
+            TerminatorKind::Terminate
             | TerminatorKind::Assert { .. }
             | TerminatorKind::Drop { .. }
             | TerminatorKind::FalseEdge { .. }
@@ -237,7 +237,7 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc
             // Nothing to do for these. Match exhaustively so this fails to compile when new
             // variants are added.
             TerminatorKind::Yield { .. }
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Assert { .. }
             | TerminatorKind::Drop { .. }
             | TerminatorKind::FalseEdge { .. }
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index d9ceac1154f..64ed7a29f6f 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -375,7 +375,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
             // need recording.
             | TerminatorKind::Return
             | TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Unreachable
             | TerminatorKind::Drop { .. } => {}
@@ -398,7 +398,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
                 ref args,
                 destination,
                 target,
-                cleanup: _,
+                unwind: _,
                 from_hir_call: _,
                 fn_span: _,
             } => {
@@ -417,7 +417,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
                 options: _,
                 line_spans: _,
                 destination: _,
-                cleanup: _,
+                unwind: _,
             } => {
                 for op in operands {
                     match *op {
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index 33a15a8d224..98bebc9b13b 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -238,7 +238,7 @@ pub trait ValueAnalysis<'tcx> {
             TerminatorKind::Goto { .. }
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::Assert { .. }
diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
index 893018e0d8e..5aed89139e2 100644
--- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
+++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
@@ -34,11 +34,6 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
             return;
         }
 
-        // This pass only runs on functions which themselves cannot unwind,
-        // forcibly changing the body of the function to structurally provide
-        // this guarantee by aborting on an unwind. If this function can unwind,
-        // then there's nothing to do because it already should work correctly.
-        //
         // Here we test for this function itself whether its ABI allows
         // unwinding or not.
         let body_ty = tcx.type_of(def_id).skip_binder();
@@ -107,31 +102,14 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls {
             }
         }
 
-        // For call instructions which need to be terminated, we insert a
-        // singular basic block which simply terminates, and then configure the
-        // `cleanup` attribute for all calls we found to this basic block we
-        // insert which means that any unwinding that happens in the functions
-        // will force an abort of the process.
-        if !calls_to_terminate.is_empty() {
-            let bb = BasicBlockData {
-                statements: Vec::new(),
-                is_cleanup: true,
-                terminator: Some(Terminator {
-                    source_info: SourceInfo::outermost(body.span),
-                    kind: TerminatorKind::Abort,
-                }),
-            };
-            let abort_bb = body.basic_blocks_mut().push(bb);
-
-            for bb in calls_to_terminate {
-                let cleanup = body.basic_blocks_mut()[bb].terminator_mut().unwind_mut().unwrap();
-                *cleanup = Some(abort_bb);
-            }
+        for id in calls_to_terminate {
+            let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap();
+            *cleanup = UnwindAction::Terminate;
         }
 
         for id in cleanups_to_remove {
             let cleanup = body.basic_blocks_mut()[id].terminator_mut().unwind_mut().unwrap();
-            *cleanup = None;
+            *cleanup = UnwindAction::Unreachable;
         }
 
         // We may have invalidated some `cleanup` blocks so clean those up now.
diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs
index 30966d22e2f..e1e354efa1c 100644
--- a/compiler/rustc_mir_transform/src/add_call_guards.rs
+++ b/compiler/rustc_mir_transform/src/add_call_guards.rs
@@ -50,10 +50,11 @@ impl AddCallGuards {
         for block in body.basic_blocks_mut() {
             match block.terminator {
                 Some(Terminator {
-                    kind: TerminatorKind::Call { target: Some(ref mut destination), cleanup, .. },
+                    kind: TerminatorKind::Call { target: Some(ref mut destination), unwind, .. },
                     source_info,
                 }) if pred_count[*destination] > 1
-                    && (cleanup.is_some() || self == &AllCallEdges) =>
+                    && (matches!(unwind, UnwindAction::Cleanup(_) | UnwindAction::Terminate)
+                        || self == &AllCallEdges) =>
                 {
                     // It's a critical edge, break it
                     let call_guard = BasicBlockData {
diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs
index 5815887e5bb..8086a4557b7 100644
--- a/compiler/rustc_mir_transform/src/check_alignment.rs
+++ b/compiler/rustc_mir_transform/src/check_alignment.rs
@@ -221,7 +221,7 @@ fn insert_alignment_check<'tcx>(
                 required: Operand::Copy(alignment),
                 found: Operand::Copy(addr),
             },
-            cleanup: None,
+            unwind: UnwindAction::Terminate,
         },
     });
 }
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index c4d058e8ecb..d908f6b3a9b 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -57,7 +57,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
             | TerminatorKind::Assert { .. }
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::FalseEdge { .. }
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index 839d5422ad1..79a9ac7d20c 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -24,7 +24,7 @@ use crate::MirPass;
 use rustc_const_eval::interpret::{
     self, compile_time_machine, AllocId, ConstAllocation, ConstValue, CtfeValidationMode, Frame,
     ImmTy, Immediate, InterpCx, InterpResult, LocalValue, MemoryKind, OpTy, PlaceTy, Pointer,
-    Scalar, StackPopCleanup, StackPopUnwind,
+    Scalar, StackPopCleanup,
 };
 
 /// The maximum number of bytes that we'll allocate space for a local or the return value.
@@ -206,7 +206,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
         _args: &[OpTy<'tcx>],
         _destination: &PlaceTy<'tcx>,
         _target: Option<BasicBlock>,
-        _unwind: StackPopUnwind,
+        _unwind: UnwindAction,
     ) -> InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> {
         Ok(None)
     }
@@ -217,7 +217,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
         _args: &[OpTy<'tcx>],
         _destination: &PlaceTy<'tcx>,
         _target: Option<BasicBlock>,
-        _unwind: StackPopUnwind,
+        _unwind: UnwindAction,
     ) -> InterpResult<'tcx> {
         throw_machine_stop_str!("calling intrinsics isn't supported in ConstProp")
     }
@@ -225,7 +225,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
     fn assert_panic(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _msg: &rustc_middle::mir::AssertMessage<'tcx>,
-        _unwind: Option<rustc_middle::mir::BasicBlock>,
+        _unwind: rustc_middle::mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         bug!("panics terminators are not evaluated in ConstProp")
     }
@@ -956,7 +956,7 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> {
             // None of these have Operands to const-propagate.
             TerminatorKind::Goto { .. }
             | TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::Drop { .. }
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index 85e229b694c..699fe44892b 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -683,7 +683,7 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
             // None of these have Operands to const-propagate.
             TerminatorKind::Goto { .. }
             | TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::Drop { .. }
diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs
index 0e7dc171a5d..725883b83fa 100644
--- a/compiler/rustc_mir_transform/src/coverage/debug.rs
+++ b/compiler/rustc_mir_transform/src/coverage/debug.rs
@@ -818,7 +818,7 @@ pub(super) fn term_type(kind: &TerminatorKind<'_>) -> &'static str {
         TerminatorKind::Goto { .. } => "Goto",
         TerminatorKind::SwitchInt { .. } => "SwitchInt",
         TerminatorKind::Resume => "Resume",
-        TerminatorKind::Abort => "Abort",
+        TerminatorKind::Terminate => "Terminate",
         TerminatorKind::Return => "Return",
         TerminatorKind::Unreachable => "Unreachable",
         TerminatorKind::Drop { .. } => "Drop",
diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs
index 6a73f2a6578..7391a77b0a6 100644
--- a/compiler/rustc_mir_transform/src/coverage/graph.rs
+++ b/compiler/rustc_mir_transform/src/coverage/graph.rs
@@ -122,7 +122,7 @@ impl CoverageGraph {
 
             match term.kind {
                 TerminatorKind::Return { .. }
-                | TerminatorKind::Abort
+                | TerminatorKind::Terminate
                 | TerminatorKind::Yield { .. }
                 | TerminatorKind::SwitchInt { .. } => {
                     // The `bb` has more than one _outgoing_ edge, or exits the function. Save the
@@ -136,7 +136,7 @@ impl CoverageGraph {
                     debug!("  because term.kind = {:?}", term.kind);
                     // Note that this condition is based on `TerminatorKind`, even though it
                     // theoretically boils down to `successors().len() != 1`; that is, either zero
-                    // (e.g., `Return`, `Abort`) or multiple successors (e.g., `SwitchInt`), but
+                    // (e.g., `Return`, `Terminate`) or multiple successors (e.g., `SwitchInt`), but
                     // since the BCB CFG ignores things like unwind branches (which exist in the
                     // `Terminator`s `successors()` list) checking the number of successors won't
                     // work.
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index 2f120258659..287ae217087 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -869,7 +869,7 @@ pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Sp
 
         // Retain spans from all other terminators
         TerminatorKind::Resume
-        | TerminatorKind::Abort
+        | TerminatorKind::Terminate
         | TerminatorKind::Return
         | TerminatorKind::Yield { .. }
         | TerminatorKind::GeneratorDrop
diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs
index 59b506e7345..0f6c06e370b 100644
--- a/compiler/rustc_mir_transform/src/coverage/tests.rs
+++ b/compiler/rustc_mir_transform/src/coverage/tests.rs
@@ -140,7 +140,7 @@ impl<'tcx> MockBlocks<'tcx> {
                 args: vec![],
                 destination: self.dummy_place.clone(),
                 target: Some(TEMP_BLOCK),
-                cleanup: None,
+                unwind: UnwindAction::Continue,
                 from_hir_call: false,
                 fn_span: DUMMY_SP,
             },
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index 15f5df41153..d4db7e2de40 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -567,7 +567,7 @@ impl<'mir, 'tcx> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachi
         _args: &[rustc_const_eval::interpret::OpTy<'tcx, Self::Provenance>],
         _destination: &rustc_const_eval::interpret::PlaceTy<'tcx, Self::Provenance>,
         _target: Option<BasicBlock>,
-        _unwind: rustc_const_eval::interpret::StackPopUnwind,
+        _unwind: UnwindAction,
     ) -> interpret::InterpResult<'tcx, Option<(&'mir Body<'tcx>, ty::Instance<'tcx>)>> {
         unimplemented!()
     }
@@ -578,7 +578,7 @@ impl<'mir, 'tcx> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachi
         _args: &[rustc_const_eval::interpret::OpTy<'tcx, Self::Provenance>],
         _destination: &rustc_const_eval::interpret::PlaceTy<'tcx, Self::Provenance>,
         _target: Option<BasicBlock>,
-        _unwind: rustc_const_eval::interpret::StackPopUnwind,
+        _unwind: UnwindAction,
     ) -> interpret::InterpResult<'tcx> {
         unimplemented!()
     }
@@ -586,7 +586,7 @@ impl<'mir, 'tcx> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachi
     fn assert_panic(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _msg: &rustc_middle::mir::AssertMessage<'tcx>,
-        _unwind: Option<BasicBlock>,
+        _unwind: UnwindAction,
     ) -> interpret::InterpResult<'tcx> {
         unimplemented!()
     }
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index 35e7efed87a..811935aa990 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -645,8 +645,8 @@ impl WriteInfo {
                 }
             }
             TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume { .. }
-            | TerminatorKind::Abort { .. }
+            | TerminatorKind::Resume
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable { .. } => (),
             TerminatorKind::Drop { .. } => {
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index a028d6356d5..a702113bd99 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -120,7 +120,7 @@ fn remove_dead_unwinds<'tcx>(
         .into_results_cursor(body);
     for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
         let place = match bb_data.terminator().kind {
-            TerminatorKind::Drop { ref place, unwind: Some(_), .. } => {
+            TerminatorKind::Drop { ref place, unwind: UnwindAction::Cleanup(_), .. } => {
                 und.derefer(place.as_ref(), body).unwrap_or(*place)
             }
             _ => continue,
@@ -160,7 +160,7 @@ fn remove_dead_unwinds<'tcx>(
     let basic_blocks = body.basic_blocks.as_mut();
     for &bb in dead_unwinds.iter() {
         if let Some(unwind) = basic_blocks[bb].terminator_mut().unwind_mut() {
-            *unwind = None;
+            *unwind = UnwindAction::Unreachable;
         }
     }
 }
@@ -399,7 +399,6 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
             let loc = Location { block: bb, statement_index: data.statements.len() };
             let terminator = data.terminator();
 
-            let resume_block = self.patch.resume_block();
             match terminator.kind {
                 TerminatorKind::Drop { mut place, target, unwind } => {
                     if let Some(new_place) = self.un_derefer.derefer(place.as_ref(), self.body) {
@@ -408,19 +407,31 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
 
                     self.init_data.seek_before(loc);
                     match self.move_data().rev_lookup.find(place.as_ref()) {
-                        LookupResult::Exact(path) => elaborate_drop(
-                            &mut Elaborator { ctxt: self },
-                            terminator.source_info,
-                            place,
-                            path,
-                            target,
-                            if data.is_cleanup {
+                        LookupResult::Exact(path) => {
+                            let unwind = if data.is_cleanup {
                                 Unwind::InCleanup
                             } else {
-                                Unwind::To(Option::unwrap_or(unwind, resume_block))
-                            },
-                            bb,
-                        ),
+                                match unwind {
+                                    UnwindAction::Cleanup(cleanup) => Unwind::To(cleanup),
+                                    UnwindAction::Continue => Unwind::To(self.patch.resume_block()),
+                                    UnwindAction::Unreachable => {
+                                        Unwind::To(self.patch.unreachable_cleanup_block())
+                                    }
+                                    UnwindAction::Terminate => {
+                                        Unwind::To(self.patch.terminate_block())
+                                    }
+                                }
+                            };
+                            elaborate_drop(
+                                &mut Elaborator { ctxt: self },
+                                terminator.source_info,
+                                place,
+                                path,
+                                target,
+                                unwind,
+                                bb,
+                            )
+                        }
                         LookupResult::Parent(..) => {
                             if !matches!(
                                 terminator.source_info.span.desugaring_kind(),
@@ -474,7 +485,10 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                 continue;
             }
             if let TerminatorKind::Call {
-                destination, target: Some(tgt), cleanup: Some(_), ..
+                destination,
+                target: Some(tgt),
+                unwind: UnwindAction::Cleanup(_),
+                ..
             } = data.terminator().kind
             {
                 assert!(!self.patch.is_patched(bb));
@@ -543,8 +557,12 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
             // There may be a critical edge after this call,
             // so mark the return as initialized *before* the
             // call.
-            if let TerminatorKind::Call { destination, target: Some(_), cleanup: None, .. } =
-                data.terminator().kind
+            if let TerminatorKind::Call {
+                destination,
+                target: Some(_),
+                unwind: UnwindAction::Continue | UnwindAction::Unreachable | UnwindAction::Terminate,
+                ..
+            } = data.terminator().kind
             {
                 assert!(!self.patch.is_patched(bb));
 
diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index 66d32b954e4..8601c1b2d71 100644
--- a/compiler/rustc_mir_transform/src/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -34,7 +34,7 @@ impl<'tcx> Visitor<'tcx> for FunctionItemRefChecker<'_, 'tcx> {
             args,
             destination: _,
             target: _,
-            cleanup: _,
+            unwind: _,
             from_hir_call: _,
             fn_span: _,
         } = &terminator.kind
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 8f29066b6e2..159780319ba 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -1060,7 +1060,12 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         let unwind = if block_data.is_cleanup {
             Unwind::InCleanup
         } else {
-            Unwind::To(unwind.unwrap_or_else(|| elaborator.patch.resume_block()))
+            Unwind::To(match *unwind {
+                UnwindAction::Cleanup(tgt) => tgt,
+                UnwindAction::Continue => elaborator.patch.resume_block(),
+                UnwindAction::Unreachable => elaborator.patch.unreachable_cleanup_block(),
+                UnwindAction::Terminate => elaborator.patch.terminate_block(),
+            })
         };
         elaborate_drop(
             &mut elaborator,
@@ -1147,7 +1152,7 @@ fn insert_panic_block<'tcx>(
         expected: true,
         msg: message,
         target: assert_block,
-        cleanup: None,
+        unwind: UnwindAction::Continue,
     };
 
     let source_info = SourceInfo::outermost(body.span);
@@ -1189,7 +1194,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
             // These never unwind.
             TerminatorKind::Goto { .. }
             | TerminatorKind::SwitchInt { .. }
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::GeneratorDrop
@@ -1248,8 +1253,8 @@ fn create_generator_resume_function<'tcx>(
             } else if !block.is_cleanup {
                 // Any terminators that *can* unwind but don't have an unwind target set are also
                 // pointed at our poisoning block (unless they're part of the cleanup path).
-                if let Some(unwind @ None) = block.terminator_mut().unwind_mut() {
-                    *unwind = Some(poison_block);
+                if let Some(unwind @ UnwindAction::Continue) = block.terminator_mut().unwind_mut() {
+                    *unwind = UnwindAction::Cleanup(poison_block);
                 }
             }
         }
@@ -1294,8 +1299,11 @@ fn create_generator_resume_function<'tcx>(
 fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock {
     let return_block = insert_term_block(body, TerminatorKind::Return);
 
-    let term =
-        TerminatorKind::Drop { place: Place::from(SELF_ARG), target: return_block, unwind: None };
+    let term = TerminatorKind::Drop {
+        place: Place::from(SELF_ARG),
+        target: return_block,
+        unwind: UnwindAction::Continue,
+    };
     let source_info = SourceInfo::outermost(body.span);
 
     // Create a block to destroy an unresumed generators. This can only destroy upvars.
@@ -1670,7 +1678,7 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
                 args,
                 destination,
                 target: Some(_),
-                cleanup: _,
+                unwind: _,
                 from_hir_call: _,
                 fn_span: _,
             } => {
@@ -1693,7 +1701,7 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
             | TerminatorKind::Goto { .. }
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::Drop { .. }
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 15b31d38394..f0cb317f449 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -453,7 +453,7 @@ impl<'tcx> Inliner<'tcx> {
 
                 // If the place doesn't actually need dropping, treat it like a regular goto.
                 let ty = callsite.callee.subst_mir(self.tcx, &place.ty(callee_body, tcx).ty);
-                if ty.needs_drop(tcx, self.param_env) && let Some(unwind) = unwind {
+                if ty.needs_drop(tcx, self.param_env) && let UnwindAction::Cleanup(unwind) = unwind {
                         work_list.push(unwind);
                     }
             } else if callee_attrs.instruction_set != self.codegen_fn_attrs.instruction_set
@@ -500,7 +500,7 @@ impl<'tcx> Inliner<'tcx> {
     ) {
         let terminator = caller_body[callsite.block].terminator.take().unwrap();
         match terminator.kind {
-            TerminatorKind::Call { args, destination, cleanup, .. } => {
+            TerminatorKind::Call { args, destination, unwind, .. } => {
                 // If the call is something like `a[*i] = f(i)`, where
                 // `i : &mut usize`, then just duplicating the `a[*i]`
                 // Place could result in two different locations if `f`
@@ -571,7 +571,7 @@ impl<'tcx> Inliner<'tcx> {
                     destination: destination_local,
                     callsite_scope: caller_body.source_scopes[callsite.source_info.scope].clone(),
                     callsite,
-                    cleanup_block: cleanup,
+                    cleanup_block: unwind,
                     in_cleanup_block: false,
                     tcx: self.tcx,
                     expn_data,
@@ -813,14 +813,14 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
                 let ty = self.instance.subst_mir(tcx, &place.ty(self.callee_body, tcx).ty);
                 if ty.needs_drop(tcx, self.param_env) {
                     self.cost += CALL_PENALTY;
-                    if unwind.is_some() {
+                    if let UnwindAction::Cleanup(_) = unwind {
                         self.cost += LANDINGPAD_PENALTY;
                     }
                 } else {
                     self.cost += INSTR_COST;
                 }
             }
-            TerminatorKind::Call { func: Operand::Constant(ref f), cleanup, .. } => {
+            TerminatorKind::Call { func: Operand::Constant(ref f), unwind, .. } => {
                 let fn_ty = self.instance.subst_mir(tcx, &f.literal.ty());
                 self.cost += if let ty::FnDef(def_id, _) = *fn_ty.kind() && tcx.is_intrinsic(def_id) {
                     // Don't give intrinsics the extra penalty for calls
@@ -828,20 +828,20 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
                 } else {
                     CALL_PENALTY
                 };
-                if cleanup.is_some() {
+                if let UnwindAction::Cleanup(_) = unwind {
                     self.cost += LANDINGPAD_PENALTY;
                 }
             }
-            TerminatorKind::Assert { cleanup, .. } => {
+            TerminatorKind::Assert { unwind, .. } => {
                 self.cost += CALL_PENALTY;
-                if cleanup.is_some() {
+                if let UnwindAction::Cleanup(_) = unwind {
                     self.cost += LANDINGPAD_PENALTY;
                 }
             }
             TerminatorKind::Resume => self.cost += RESUME_PENALTY,
-            TerminatorKind::InlineAsm { cleanup, .. } => {
+            TerminatorKind::InlineAsm { unwind, .. } => {
                 self.cost += INSTR_COST;
-                if cleanup.is_some() {
+                if let UnwindAction::Cleanup(_) = unwind {
                     self.cost += LANDINGPAD_PENALTY;
                 }
             }
@@ -979,7 +979,7 @@ struct Integrator<'a, 'tcx> {
     destination: Local,
     callsite_scope: SourceScopeData<'tcx>,
     callsite: &'a CallSite<'tcx>,
-    cleanup_block: Option<BasicBlock>,
+    cleanup_block: UnwindAction,
     in_cleanup_block: bool,
     tcx: TyCtxt<'tcx>,
     expn_data: LocalExpnId,
@@ -1014,18 +1014,21 @@ impl Integrator<'_, '_> {
         new
     }
 
-    fn map_unwind(&self, unwind: Option<BasicBlock>) -> Option<BasicBlock> {
+    fn map_unwind(&self, unwind: UnwindAction) -> UnwindAction {
         if self.in_cleanup_block {
-            if unwind.is_some() {
-                bug!("cleanup on cleanup block");
+            match unwind {
+                UnwindAction::Cleanup(_) | UnwindAction::Continue => {
+                    bug!("cleanup on cleanup block");
+                }
+                UnwindAction::Unreachable | UnwindAction::Terminate => return unwind,
             }
-            return unwind;
         }
 
         match unwind {
-            Some(target) => Some(self.map_block(target)),
+            UnwindAction::Unreachable | UnwindAction::Terminate => unwind,
+            UnwindAction::Cleanup(target) => UnwindAction::Cleanup(self.map_block(target)),
             // Add an unwind edge to the original call's cleanup block
-            None => self.cleanup_block,
+            UnwindAction::Continue => self.cleanup_block,
         }
     }
 }
@@ -1116,15 +1119,15 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
                 *target = self.map_block(*target);
                 *unwind = self.map_unwind(*unwind);
             }
-            TerminatorKind::Call { ref mut target, ref mut cleanup, .. } => {
+            TerminatorKind::Call { ref mut target, ref mut unwind, .. } => {
                 if let Some(ref mut tgt) = *target {
                     *tgt = self.map_block(*tgt);
                 }
-                *cleanup = self.map_unwind(*cleanup);
+                *unwind = self.map_unwind(*unwind);
             }
-            TerminatorKind::Assert { ref mut target, ref mut cleanup, .. } => {
+            TerminatorKind::Assert { ref mut target, ref mut unwind, .. } => {
                 *target = self.map_block(*target);
-                *cleanup = self.map_unwind(*cleanup);
+                *unwind = self.map_unwind(*unwind);
             }
             TerminatorKind::Return => {
                 terminator.kind = if let Some(tgt) = self.callsite.target {
@@ -1134,11 +1137,14 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
                 }
             }
             TerminatorKind::Resume => {
-                if let Some(tgt) = self.cleanup_block {
-                    terminator.kind = TerminatorKind::Goto { target: tgt }
-                }
+                terminator.kind = match self.cleanup_block {
+                    UnwindAction::Cleanup(tgt) => TerminatorKind::Goto { target: tgt },
+                    UnwindAction::Continue => TerminatorKind::Resume,
+                    UnwindAction::Unreachable => TerminatorKind::Unreachable,
+                    UnwindAction::Terminate => TerminatorKind::Terminate,
+                };
             }
-            TerminatorKind::Abort => {}
+            TerminatorKind::Terminate => {}
             TerminatorKind::Unreachable => {}
             TerminatorKind::FalseEdge { ref mut real_target, ref mut imaginary_target } => {
                 *real_target = self.map_block(*real_target);
@@ -1149,11 +1155,11 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
             {
                 bug!("False unwinds should have been removed before inlining")
             }
-            TerminatorKind::InlineAsm { ref mut destination, ref mut cleanup, .. } => {
+            TerminatorKind::InlineAsm { ref mut destination, ref mut unwind, .. } => {
                 if let Some(ref mut tgt) = *destination {
                     *tgt = self.map_block(*tgt);
                 }
-                *cleanup = self.map_unwind(*cleanup);
+                *unwind = self.map_unwind(*unwind);
             }
         }
     }
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index b52de4b72c9..2e418c1dafc 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -159,7 +159,7 @@ fn remap_mir_for_const_eval_select<'tcx>(
                 ref mut args,
                 destination,
                 target,
-                cleanup,
+                unwind,
                 fn_span,
                 ..
             } if let ty::FnDef(def_id, _) = *literal.ty().kind()
@@ -196,7 +196,7 @@ fn remap_mir_for_const_eval_select<'tcx>(
                     };
                     method(place)
                 }).collect();
-                terminator.kind = TerminatorKind::Call { func, args: arguments, destination, target, cleanup, from_hir_call: false, fn_span };
+                terminator.kind = TerminatorKind::Call { func, args: arguments, destination, target, unwind, from_hir_call: false, fn_span };
             }
             _ => {}
         }
diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs
index 101fae2f08c..7dc5878e047 100644
--- a/compiler/rustc_mir_transform/src/lower_slice_len.rs
+++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs
@@ -54,7 +54,6 @@ fn lower_slice_len_call<'tcx>(
             args,
             destination,
             target: Some(bb),
-            cleanup: None,
             from_hir_call: true,
             ..
         } => {
diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
index e962819b691..4941c9edce3 100644
--- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
+++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
@@ -72,7 +72,7 @@ impl RemoveNoopLandingPads {
             TerminatorKind::GeneratorDrop
             | TerminatorKind::Yield { .. }
             | TerminatorKind::Return
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Unreachable
             | TerminatorKind::Call { .. }
             | TerminatorKind::Assert { .. }
@@ -103,11 +103,11 @@ impl RemoveNoopLandingPads {
         for bb in postorder {
             debug!("  processing {:?}", bb);
             if let Some(unwind) = body[bb].terminator_mut().unwind_mut() {
-                if let Some(unwind_bb) = *unwind {
+                if let UnwindAction::Cleanup(unwind_bb) = *unwind {
                     if nop_landing_pads.contains(unwind_bb) {
                         debug!("    removing noop landing pad");
                         landing_pads_removed += 1;
-                        *unwind = None;
+                        *unwind = UnwindAction::Continue;
                     }
                 }
             }
diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs
index d76ab95faba..ef367faf6a7 100644
--- a/compiler/rustc_mir_transform/src/separate_const_switch.rs
+++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs
@@ -112,7 +112,7 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize {
                         | TerminatorKind::Assert { .. }
                         | TerminatorKind::FalseUnwind { .. }
                         | TerminatorKind::Yield { .. }
-                        | TerminatorKind::Abort
+                        | TerminatorKind::Terminate
                         | TerminatorKind::Return
                         | TerminatorKind::Unreachable
                         | TerminatorKind::InlineAsm { .. }
@@ -164,7 +164,7 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize {
             }
 
             TerminatorKind::Resume
-            | TerminatorKind::Abort
+            | TerminatorKind::Terminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::GeneratorDrop
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 9e406eba0fc..2787fe2ce42 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -499,7 +499,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
                 args: vec![Operand::Move(ref_loc)],
                 destination: dest,
                 target: Some(next),
-                cleanup: Some(cleanup),
+                unwind: UnwindAction::Cleanup(cleanup),
                 from_hir_call: true,
                 fn_span: self.span,
             },
@@ -540,7 +540,11 @@ impl<'tcx> CloneShimBuilder<'tcx> {
             self.make_clone_call(dest_field, src_field, ity, next_block, unwind);
             self.block(
                 vec![],
-                TerminatorKind::Drop { place: dest_field, target: unwind, unwind: None },
+                TerminatorKind::Drop {
+                    place: dest_field,
+                    target: unwind,
+                    unwind: UnwindAction::Terminate,
+                },
                 true,
             );
             unwind = next_unwind;
@@ -776,10 +780,10 @@ fn build_call_shim<'tcx>(
             args,
             destination: Place::return_place(),
             target: Some(BasicBlock::new(1)),
-            cleanup: if let Some(Adjustment::RefMut) = rcvr_adjustment {
-                Some(BasicBlock::new(3))
+            unwind: if let Some(Adjustment::RefMut) = rcvr_adjustment {
+                UnwindAction::Cleanup(BasicBlock::new(3))
             } else {
-                None
+                UnwindAction::Continue
             },
             from_hir_call: true,
             fn_span: span,
@@ -792,7 +796,11 @@ fn build_call_shim<'tcx>(
         block(
             &mut blocks,
             vec![],
-            TerminatorKind::Drop { place: rcvr_place(), target: BasicBlock::new(2), unwind: None },
+            TerminatorKind::Drop {
+                place: rcvr_place(),
+                target: BasicBlock::new(2),
+                unwind: UnwindAction::Continue,
+            },
             false,
         );
     }
@@ -803,7 +811,11 @@ fn build_call_shim<'tcx>(
         block(
             &mut blocks,
             vec![],
-            TerminatorKind::Drop { place: rcvr_place(), target: BasicBlock::new(4), unwind: None },
+            TerminatorKind::Drop {
+                place: rcvr_place(),
+                target: BasicBlock::new(4),
+                unwind: UnwindAction::Terminate,
+            },
             true,
         );
 
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index f41edff8513..7bcff7e07fb 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -852,7 +852,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
                     self.output.push(create_fn_mono_item(tcx, instance, source));
                 }
             }
-            mir::TerminatorKind::Abort { .. } => {
+            mir::TerminatorKind::Terminate { .. } => {
                 let instance = Instance::mono(
                     tcx,
                     tcx.require_lang_item(LangItem::PanicCannotUnwind, Some(source)),
@@ -872,6 +872,16 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
             | mir::TerminatorKind::FalseUnwind { .. } => bug!(),
         }
 
+        if let Some(mir::UnwindAction::Terminate) = terminator.unwind() {
+            let instance = Instance::mono(
+                tcx,
+                tcx.require_lang_item(LangItem::PanicCannotUnwind, Some(source)),
+            );
+            if should_codegen_locally(tcx, &instance) {
+                self.output.push(create_fn_mono_item(tcx, instance, source));
+            }
+        }
+
         self.super_terminator(terminator, location);
     }
 
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 5210b8fe69d..e03ce5d7120 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -423,11 +423,11 @@ impl<'a> Parser<'a> {
         if let token::Literal(Lit {
             kind: token::LitKind::Integer | token::LitKind::Float,
             symbol,
-            suffix,
+            suffix: Some(suffix), // no suffix makes it a valid literal
         }) = self.token.kind
             && rustc_ast::MetaItemLit::from_token(&self.token).is_none()
         {
-            Some((symbol.as_str().len(), suffix.unwrap()))
+            Some((symbol.as_str().len(), suffix))
         } else {
             None
         }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index e69a9d0aeca..0c9d306081e 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1607,7 +1607,17 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         let mut err =
             struct_span_err!(self.tcx.sess, ident.span, E0603, "{} `{}` is private", descr, ident);
         err.span_label(ident.span, &format!("private {}", descr));
-        if let Some(span) = ctor_fields_span {
+
+        let mut non_exhaustive = None;
+        // If an ADT is foreign and marked as `non_exhaustive`, then that's
+        // probably why we have the privacy error.
+        // Otherwise, point out if the struct has any private fields.
+        if let Some(def_id) = res.opt_def_id()
+            && !def_id.is_local()
+            && let Some(attr) = self.tcx.get_attr(def_id, sym::non_exhaustive)
+        {
+            non_exhaustive = Some(attr.span);
+        } else if let Some(span) = ctor_fields_span {
             err.span_label(span, "a constructor is private if any of the fields is private");
             if let Res::Def(_, d) = res && let Some(fields) = self.field_visibility_spans.get(&d) {
                 err.multipart_suggestion_verbose(
@@ -1656,6 +1666,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
             if !first && binding.vis.is_public() {
                 note_span.push_span_label(def_span, "consider importing it directly");
             }
+            // Final step in the import chain, point out if the ADT is `non_exhaustive`
+            // which is probably why this privacy violation occurred.
+            if next_binding.is_none() && let Some(span) = non_exhaustive {
+                note_span.push_span_label(
+                    span,
+                    format!("cannot be constructed because it is `#[non_exhaustive]`"),
+                );
+            }
             err.span_note(note_span, &msg);
         }
 
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 19f46d45af6..b1a696d093e 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -122,6 +122,12 @@ pub(crate) enum ConstantItemKind {
     Static,
 }
 
+#[derive(Debug, Copy, Clone, PartialEq, Eq)]
+enum RecordPartialRes {
+    Yes,
+    No,
+}
+
 /// The rib kind restricts certain accesses,
 /// e.g. to a `Res::Local` of an outer item.
 #[derive(Copy, Clone, Debug)]
@@ -2682,6 +2688,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 &path,
                 PathSource::Trait(AliasPossibility::No),
                 Finalize::new(trait_ref.ref_id, trait_ref.path.span),
+                RecordPartialRes::Yes,
             );
             self.diagnostic_metadata.currently_processing_impl_trait = None;
             if let Some(def_id) = res.expect_full_res().opt_def_id() {
@@ -3420,6 +3427,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             &Segment::from_path(path),
             source,
             Finalize::new(id, path.span),
+            RecordPartialRes::Yes,
         );
     }
 
@@ -3430,6 +3438,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         path: &[Segment],
         source: PathSource<'ast>,
         finalize: Finalize,
+        record_partial_res: RecordPartialRes,
     ) -> PartialRes {
         let ns = source.namespace();
 
@@ -3636,7 +3645,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             _ => report_errors(self, None),
         };
 
-        if !matches!(source, PathSource::TraitItem(..)) {
+        if record_partial_res == RecordPartialRes::Yes {
             // Avoid recording definition of `A::B` in `<T as A>::B::C`.
             self.r.record_partial_res(node_id, partial_res);
             self.resolve_elided_lifetimes_in_path(node_id, partial_res, path, source, path_span);
@@ -3740,7 +3749,25 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 )));
             }
 
-            // Make sure `A::B` in `<T as A::B>::C` is a trait item.
+            let num_privacy_errors = self.r.privacy_errors.len();
+            // Make sure that `A` in `<T as A>::B::C` is a trait.
+            let trait_res = self.smart_resolve_path_fragment(
+                &None,
+                &path[..qself.position],
+                PathSource::Trait(AliasPossibility::No),
+                Finalize::new(finalize.node_id, qself.path_span),
+                RecordPartialRes::No,
+            );
+
+            if trait_res.expect_full_res() == Res::Err {
+                return Ok(Some(trait_res));
+            }
+
+            // Truncate additional privacy errors reported above,
+            // because they'll be recomputed below.
+            self.r.privacy_errors.truncate(num_privacy_errors);
+
+            // Make sure `A::B` in `<T as A>::B::C` is a trait item.
             //
             // Currently, `path` names the full item (`A::B::C`, in
             // our example). so we extract the prefix of that that is
@@ -3753,6 +3780,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 &path[..=qself.position],
                 PathSource::TraitItem(ns),
                 Finalize::with_root_span(finalize.node_id, finalize.path_span, qself.path_span),
+                RecordPartialRes::No,
             );
 
             // The remaining segments (the `C` in our example) will
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 86e30dd0f6a..0befff894ef 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -143,7 +143,7 @@ fn rustc_terminator_to_terminator(
             otherwise: targets.otherwise().as_usize(),
         },
         Resume => Terminator::Resume,
-        Abort => Terminator::Abort,
+        Terminate => Terminator::Abort,
         Return => Terminator::Return,
         Unreachable => Terminator::Unreachable,
         Drop { .. } => todo!(),
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 0e55e81143d..7affad9aa01 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1496,6 +1496,7 @@ symbols! {
         trait_alias,
         trait_upcasting,
         transmute,
+        transmute_generic_consts,
         transmute_opts,
         transmute_trait,
         transparent,
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index cac7ff72267..ee883285531 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -1,5 +1,5 @@
 use rustc_data_structures::base_n;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::intern::Interned;
 use rustc_hir as hir;
 use rustc_hir::def::CtorKind;
@@ -81,9 +81,9 @@ pub(super) fn mangle_typeid_for_trait_ref<'tcx>(
 struct BinderLevel {
     /// The range of distances from the root of what's
     /// being printed, to the lifetimes in a binder.
-    /// Specifically, a `BrAnon(i)` lifetime has depth
-    /// `lifetime_depths.start + i`, going away from the
-    /// the root and towards its use site, as `i` increases.
+    /// Specifically, a `BrAnon` lifetime has depth
+    /// `lifetime_depths.start + index`, going away from the
+    /// the root and towards its use site, as the var index increases.
     /// This is used to flatten rustc's pairing of `BrAnon`
     /// (intra-binder disambiguation) with a `DebruijnIndex`
     /// (binder addressing), to "true" de Bruijn indices,
@@ -208,24 +208,15 @@ impl<'tcx> SymbolMangler<'tcx> {
     where
         T: TypeVisitable<TyCtxt<'tcx>>,
     {
-        // FIXME(non-lifetime-binders): What to do here?
-        let regions = if value.has_late_bound_regions() {
-            self.tcx.collect_referenced_late_bound_regions(value)
-        } else {
-            FxHashSet::default()
-        };
-
         let mut lifetime_depths =
             self.binders.last().map(|b| b.lifetime_depths.end).map_or(0..0, |i| i..i);
 
-        let lifetimes = regions
-            .into_iter()
-            .map(|br| match br {
-                ty::BrAnon(i, _) => i,
-                _ => bug!("symbol_names: non-anonymized region `{:?}` in `{:?}`", br, value),
-            })
-            .max()
-            .map_or(0, |max| max + 1);
+        // FIXME(non-lifetime-binders): What to do here?
+        let lifetimes = value
+            .bound_vars()
+            .iter()
+            .filter(|var| matches!(var, ty::BoundVariableKind::Region(..)))
+            .count() as u32;
 
         self.push_opt_integer_62("G", lifetimes as u64);
         lifetime_depths.end += lifetimes;
@@ -338,9 +329,9 @@ impl<'tcx> Printer<'tcx> for &mut SymbolMangler<'tcx> {
 
             // Late-bound lifetimes use indices starting at 1,
             // see `BinderLevel` for more details.
-            ty::ReLateBound(debruijn, ty::BoundRegion { kind: ty::BrAnon(i, _), .. }) => {
+            ty::ReLateBound(debruijn, ty::BoundRegion { var, kind: ty::BrAnon(_) }) => {
                 let binder = &self.binders[self.binders.len() - 1 - debruijn.index()];
-                let depth = binder.lifetime_depths.start + i;
+                let depth = binder.lifetime_depths.start + var.as_u32();
 
                 1 + (self.binders.last().unwrap().lifetime_depths.end - 1 - depth)
             }
diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
index 2e5a8b7debc..55025e2e72b 100644
--- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs
+++ b/compiler/rustc_trait_selection/src/solve/canonicalize.rs
@@ -257,7 +257,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
             self.primitive_var_infos.push(CanonicalVarInfo { kind });
             var
         });
-        let br = ty::BoundRegion { var, kind: BrAnon(var.as_u32(), None) };
+        let br = ty::BoundRegion { var, kind: BrAnon(None) };
         self.interner().mk_re_late_bound(self.binder_index, br)
     }
 
@@ -300,14 +300,20 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
             ty::Placeholder(placeholder) => match self.canonicalize_mode {
                 CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(ty::Placeholder {
                     universe: placeholder.universe,
-                    name: BoundTyKind::Anon(self.variables.len() as u32),
+                    bound: ty::BoundTy {
+                        var: ty::BoundVar::from_usize(self.variables.len()),
+                        kind: ty::BoundTyKind::Anon,
+                    },
                 }),
                 CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder),
             },
             ty::Param(_) => match self.canonicalize_mode {
                 CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(ty::Placeholder {
                     universe: ty::UniverseIndex::ROOT,
-                    name: ty::BoundTyKind::Anon(self.variables.len() as u32),
+                    bound: ty::BoundTy {
+                        var: ty::BoundVar::from_usize(self.variables.len()),
+                        kind: ty::BoundTyKind::Anon,
+                    },
                 }),
                 CanonicalizeMode::Response { .. } => bug!("param ty in response: {t:?}"),
             },
@@ -345,7 +351,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
                 var
             }),
         );
-        let bt = ty::BoundTy { var, kind: BoundTyKind::Anon(var.index() as u32) };
+        let bt = ty::BoundTy { var, kind: BoundTyKind::Anon };
         self.interner().mk_bound(self.binder_index, bt)
     }
 
@@ -373,7 +379,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
                 CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
                     ty::Placeholder {
                         universe: placeholder.universe,
-                        name: ty::BoundVar::from(self.variables.len()),
+                        bound: ty::BoundVar::from(self.variables.len()),
                     },
                     c.ty(),
                 ),
@@ -385,7 +391,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
                 CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
                     ty::Placeholder {
                         universe: ty::UniverseIndex::ROOT,
-                        name: ty::BoundVar::from(self.variables.len()),
+                        bound: ty::BoundVar::from(self.variables.len()),
                     },
                     c.ty(),
                 ),
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
index ee90488730a..714b6dfb717 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -188,7 +188,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
                 } else {
                     // For placeholders which were already part of the input, we simply map this
                     // universal bound variable back the placeholder of the input.
-                    original_values[info.expect_anon_placeholder() as usize]
+                    original_values[info.expect_placeholder_index()]
                 }
             },
         ));
diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs
index 4a3b7e42bac..9e851b788a5 100644
--- a/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs
+++ b/compiler/rustc_trait_selection/src/solve/trait_goals/structural_traits.rs
@@ -95,17 +95,15 @@ fn replace_erased_lifetimes_with_bound_vars<'tcx>(
     let mut counter = 0;
     let ty = tcx.fold_regions(ty, |mut r, current_depth| {
         if let ty::ReErased = r.kind() {
-            let br = ty::BoundRegion {
-                var: ty::BoundVar::from_u32(counter),
-                kind: ty::BrAnon(counter, None),
-            };
+            let br =
+                ty::BoundRegion { var: ty::BoundVar::from_u32(counter), kind: ty::BrAnon(None) };
             counter += 1;
             r = tcx.mk_re_late_bound(current_depth, br);
         }
         r
     });
     let bound_vars = tcx.mk_bound_variable_kinds_from_iter(
-        (0..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i, None))),
+        (0..counter).map(|_| ty::BoundVariableKind::Region(ty::BrAnon(None))),
     );
     ty::Binder::bind_with_vars(ty, bound_vars)
 }
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index b8d9cff9c48..826fc63ca06 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -772,7 +772,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> {
             }
             ty::ReLateBound(debruijn, br) if debruijn >= self.current_index => {
                 let universe = self.universe_for(debruijn);
-                let p = ty::PlaceholderRegion { universe, name: br.kind };
+                let p = ty::PlaceholderRegion { universe, bound: br };
                 self.mapped_regions.insert(p, br);
                 self.infcx.tcx.mk_re_placeholder(p)
             }
@@ -790,7 +790,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> {
             }
             ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => {
                 let universe = self.universe_for(debruijn);
-                let p = ty::PlaceholderType { universe, name: bound_ty.kind };
+                let p = ty::PlaceholderType { universe, bound: bound_ty };
                 self.mapped_types.insert(p, bound_ty);
                 self.infcx.tcx.mk_placeholder(p)
             }
@@ -809,7 +809,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> {
             }
             ty::ConstKind::Bound(debruijn, bound_const) if debruijn >= self.current_index => {
                 let universe = self.universe_for(debruijn);
-                let p = ty::PlaceholderConst { universe, name: bound_const };
+                let p = ty::PlaceholderConst { universe, bound: bound_const };
                 self.mapped_consts.insert(p, bound_const);
                 self.infcx.tcx.mk_const(p, ct.ty())
             }
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index b58e62536d6..6bb53418bea 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2,12 +2,6 @@
 //!
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html#selection
 
-// FIXME: The `map` field in ProvisionalEvaluationCache should be changed to
-// a `FxIndexMap` to avoid query instability, but right now it causes a perf regression. This would be
-// fixed or at least lightened by the addition of the `drain_filter` method to `FxIndexMap`
-// Relevant: https://github.com/rust-lang/rust/pull/103723 and https://github.com/bluss/indexmap/issues/242
-#![allow(rustc::potential_query_instability)]
-
 use self::EvaluationResult::*;
 use self::SelectionCandidate::*;
 
@@ -32,8 +26,7 @@ use crate::traits::project::ProjectAndUnifyResult;
 use crate::traits::project::ProjectionCacheKeyExt;
 use crate::traits::ProjectionCacheKey;
 use crate::traits::Unimplemented;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
+use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::Diagnostic;
 use rustc_hir as hir;
@@ -2782,7 +2775,7 @@ struct ProvisionalEvaluationCache<'tcx> {
     /// - then we determine that `E` is in error -- we will then clear
     ///   all cache values whose DFN is >= 4 -- in this case, that
     ///   means the cached value for `F`.
-    map: RefCell<FxHashMap<ty::PolyTraitPredicate<'tcx>, ProvisionalEvaluation>>,
+    map: RefCell<FxIndexMap<ty::PolyTraitPredicate<'tcx>, ProvisionalEvaluation>>,
 
     /// The stack of args that we assume to be true because a `WF(arg)` predicate
     /// is on the stack above (and because of wellformedness is coinductive).
@@ -2930,12 +2923,13 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> {
     /// have a performance impact in practice.
     fn on_completion(&self, dfn: usize) {
         debug!(?dfn, "on_completion");
-
-        for (fresh_trait_pred, eval) in
-            self.map.borrow_mut().drain_filter(|_k, eval| eval.from_dfn >= dfn)
-        {
-            debug!(?fresh_trait_pred, ?eval, "on_completion");
-        }
+        self.map.borrow_mut().retain(|fresh_trait_pred, eval| {
+            if eval.from_dfn >= dfn {
+                debug!(?fresh_trait_pred, ?eval, "on_completion");
+                return false;
+            }
+            true
+        });
     }
 }
 
@@ -3017,7 +3011,7 @@ fn bind_generator_hidden_types_above<'tcx>(
                     if let ty::ReErased = r.kind() {
                         let br = ty::BoundRegion {
                             var: ty::BoundVar::from_u32(counter),
-                            kind: ty::BrAnon(counter, None),
+                            kind: ty::BrAnon(None),
                         };
                         counter += 1;
                         r = tcx.mk_re_late_bound(current_depth, br);
@@ -3033,7 +3027,7 @@ fn bind_generator_hidden_types_above<'tcx>(
         debug_assert!(!hidden_types.has_erased_regions());
     }
     let bound_vars = tcx.mk_bound_variable_kinds_from_iter(bound_vars.iter().chain(
-        (num_bound_variables..counter).map(|i| ty::BoundVariableKind::Region(ty::BrAnon(i, None))),
+        (num_bound_variables..counter).map(|_| ty::BoundVariableKind::Region(ty::BrAnon(None))),
     ));
     ty::Binder::bind_with_vars(hidden_types, bound_vars)
 }
diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs
index f8c8f744e6d..9683e48478e 100644
--- a/compiler/rustc_traits/src/chalk/db.rs
+++ b/compiler/rustc_traits/src/chalk/db.rs
@@ -730,7 +730,7 @@ fn bound_vars_for_item(tcx: TyCtxt<'_>, def_id: DefId) -> SubstsRef<'_> {
         ty::GenericParamDefKind::Lifetime => {
             let br = ty::BoundRegion {
                 var: ty::BoundVar::from_usize(substs.len()),
-                kind: ty::BrAnon(substs.len() as u32, None),
+                kind: ty::BrAnon(None),
             };
             tcx.mk_re_late_bound(ty::INNERMOST, br).into()
         }
diff --git a/compiler/rustc_traits/src/chalk/lowering.rs b/compiler/rustc_traits/src/chalk/lowering.rs
index 527f6013a15..2be72879b7b 100644
--- a/compiler/rustc_traits/src/chalk/lowering.rs
+++ b/compiler/rustc_traits/src/chalk/lowering.rs
@@ -376,7 +376,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty<RustInterner<'tcx>>> for Ty<'tcx> {
             ty::Placeholder(_placeholder) => {
                 chalk_ir::TyKind::Placeholder(chalk_ir::PlaceholderIndex {
                     ui: chalk_ir::UniverseIndex { counter: _placeholder.universe.as_usize() },
-                    idx: _placeholder.name.expect_anon() as usize,
+                    idx: _placeholder.bound.var.as_usize(),
                 })
             }
             ty::Infer(_infer) => unimplemented!(),
@@ -479,12 +479,15 @@ impl<'tcx> LowerInto<'tcx, Ty<'tcx>> for &chalk_ir::Ty<RustInterner<'tcx>> {
                 ty::DebruijnIndex::from_usize(bound.debruijn.depth() as usize),
                 ty::BoundTy {
                     var: ty::BoundVar::from_usize(bound.index),
-                    kind: ty::BoundTyKind::Anon(bound.index as u32),
+                    kind: ty::BoundTyKind::Anon,
                 },
             ),
             TyKind::Placeholder(placeholder) => ty::Placeholder(ty::Placeholder {
                 universe: ty::UniverseIndex::from_usize(placeholder.ui.counter),
-                name: ty::BoundTyKind::Anon(placeholder.idx as u32),
+                bound: ty::BoundTy {
+                    var: ty::BoundVar::from_usize(placeholder.idx),
+                    kind: ty::BoundTyKind::Anon,
+                },
             }),
             TyKind::InferenceVar(_, _) => unimplemented!(),
             TyKind::Dyn(_) => unimplemented!(),
@@ -530,13 +533,16 @@ impl<'tcx> LowerInto<'tcx, Region<'tcx>> for &chalk_ir::Lifetime<RustInterner<'t
                 ty::DebruijnIndex::from_u32(var.debruijn.depth()),
                 ty::BoundRegion {
                     var: ty::BoundVar::from_usize(var.index),
-                    kind: ty::BrAnon(var.index as u32, None),
+                    kind: ty::BrAnon(None),
                 },
             ),
             chalk_ir::LifetimeData::InferenceVar(_var) => unimplemented!(),
             chalk_ir::LifetimeData::Placeholder(p) => tcx.mk_re_placeholder(ty::Placeholder {
                 universe: ty::UniverseIndex::from_usize(p.ui.counter),
-                name: ty::BoundRegionKind::BrAnon(p.idx as u32, None),
+                bound: ty::BoundRegion {
+                    var: ty::BoundVar::from_usize(p.idx),
+                    kind: ty::BoundRegionKind::BrAnon(None),
+                },
             }),
             chalk_ir::LifetimeData::Static => tcx.lifetimes.re_static,
             chalk_ir::LifetimeData::Erased => tcx.lifetimes.re_erased,
@@ -685,7 +691,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Binders<chalk_ir::QuantifiedWhereClauses<Ru
         let self_ty = interner.tcx.mk_bound(
             // This is going to be wrapped in a binder
             ty::DebruijnIndex::from_usize(1),
-            ty::BoundTy { var: ty::BoundVar::from_usize(0), kind: ty::BoundTyKind::Anon(0) },
+            ty::BoundTy { var: ty::BoundVar::from_usize(0), kind: ty::BoundTyKind::Anon },
         );
         let where_clauses = predicates.into_iter().map(|predicate| {
             let (predicate, binders, _named_regions) =
@@ -970,7 +976,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for BoundVarsCollector<'tcx> {
                     }
                 }
 
-                ty::BoundRegionKind::BrAnon(var, _) => match self.parameters.entry(var) {
+                ty::BoundRegionKind::BrAnon(_) => match self.parameters.entry(br.var.as_u32()) {
                     Entry::Vacant(entry) => {
                         entry.insert(chalk_ir::VariableKind::Lifetime);
                     }
@@ -1030,8 +1036,8 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for NamedBoundVarSubstitutor<'a, 'tcx> {
         match *r {
             ty::ReLateBound(index, br) if index == self.binder_index => match br.kind {
                 ty::BrNamed(def_id, _name) => match self.named_parameters.get(&def_id) {
-                    Some(idx) => {
-                        let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(*idx, None) };
+                    Some(_) => {
+                        let new_br = ty::BoundRegion { var: br.var, kind: ty::BrAnon(None) };
                         return self.tcx.mk_re_late_bound(index, new_br);
                     }
                     None => panic!("Missing `BrNamed`."),
@@ -1090,7 +1096,10 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamsSubstitutor<'tcx> {
             ty::Param(param) => match self.list.iter().position(|r| r == &param) {
                 Some(idx) => self.tcx.mk_placeholder(ty::PlaceholderType {
                     universe: ty::UniverseIndex::from_usize(0),
-                    name: ty::BoundTyKind::Anon(idx as u32),
+                    bound: ty::BoundTy {
+                        var: ty::BoundVar::from_usize(idx),
+                        kind: ty::BoundTyKind::Anon,
+                    },
                 }),
                 None => {
                     self.list.push(param);
@@ -1098,7 +1107,10 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamsSubstitutor<'tcx> {
                     self.params.insert(idx as u32, param);
                     self.tcx.mk_placeholder(ty::PlaceholderType {
                         universe: ty::UniverseIndex::from_usize(0),
-                        name: ty::BoundTyKind::Anon(idx as u32),
+                        bound: ty::BoundTy {
+                            var: ty::BoundVar::from_usize(idx),
+                            kind: ty::BoundTyKind::Anon,
+                        },
                     })
                 }
             },
@@ -1115,7 +1127,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamsSubstitutor<'tcx> {
                 Some(idx) => {
                     let br = ty::BoundRegion {
                         var: ty::BoundVar::from_u32(*idx),
-                        kind: ty::BrAnon(*idx, None),
+                        kind: ty::BrAnon(None),
                     };
                     self.tcx.mk_re_late_bound(self.binder_index, br)
                 }
@@ -1123,7 +1135,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ParamsSubstitutor<'tcx> {
                     let idx = self.named_regions.len() as u32;
                     let br = ty::BoundRegion {
                         var: ty::BoundVar::from_u32(idx),
-                        kind: ty::BrAnon(idx, None),
+                        kind: ty::BrAnon(None),
                     };
                     self.named_regions.insert(_re.def_id, idx);
                     self.tcx.mk_re_late_bound(self.binder_index, br)
@@ -1156,8 +1168,8 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for ReverseParamsSubstitutor<'tcx> {
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
         match *t.kind() {
-            ty::Placeholder(ty::PlaceholderType { universe: ty::UniverseIndex::ROOT, name }) => {
-                match self.params.get(&name.expect_anon()) {
+            ty::Placeholder(ty::PlaceholderType { universe: ty::UniverseIndex::ROOT, bound }) => {
+                match self.params.get(&bound.var.as_u32()) {
                     Some(&ty::ParamTy { index, name }) => self.tcx.mk_ty_param(index, name),
                     None => t,
                 }
@@ -1189,8 +1201,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for PlaceholdersCollector {
     fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
         match t.kind() {
             ty::Placeholder(p) if p.universe == self.universe_index => {
-                self.next_ty_placeholder =
-                    self.next_ty_placeholder.max(p.name.expect_anon() as usize + 1);
+                self.next_ty_placeholder = self.next_ty_placeholder.max(p.bound.var.as_usize() + 1);
             }
 
             _ => (),
@@ -1202,8 +1213,9 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for PlaceholdersCollector {
     fn visit_region(&mut self, r: Region<'tcx>) -> ControlFlow<Self::BreakTy> {
         match *r {
             ty::RePlaceholder(p) if p.universe == self.universe_index => {
-                if let ty::BoundRegionKind::BrAnon(anon, _) = p.name {
-                    self.next_anon_region_placeholder = self.next_anon_region_placeholder.max(anon);
+                if let ty::BoundRegionKind::BrAnon(_) = p.bound.kind {
+                    self.next_anon_region_placeholder =
+                        self.next_anon_region_placeholder.max(p.bound.var.as_u32());
                 }
                 // FIXME: This doesn't seem to handle BrNamed at all?
             }
diff --git a/config.example.toml b/config.example.toml
index 5ef83760aed..15c6bc0f123 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -16,7 +16,7 @@
 # Use different pre-set defaults than the global defaults.
 #
 # See `src/bootstrap/defaults` for more information.
-# Note that this has no default value (x.py uses the defaults in `config.toml.example`).
+# Note that this has no default value (x.py uses the defaults in `config.example.toml`).
 #profile = <none>
 
 # Keeps track of the last version of `x.py` used.
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index 8a8d4caf96f..5888e2960bb 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -764,6 +764,7 @@ where
 {
     type Error = U::Error;
 
+    #[inline]
     fn try_into(self) -> Result<U, U::Error> {
         U::try_from(self)
     }
@@ -779,6 +780,7 @@ where
 {
     type Error = Infallible;
 
+    #[inline]
     fn try_from(value: U) -> Result<Self, Self::Error> {
         Ok(U::into(value))
     }
diff --git a/library/core/src/num/shells/u16.rs b/library/core/src/num/shells/u16.rs
index b203806f460..7394977e507 100644
--- a/library/core/src/num/shells/u16.rs
+++ b/library/core/src/num/shells/u16.rs
@@ -1,4 +1,4 @@
-//! Redundant constants module for the [`i16` primitive type][i16].
+//! Redundant constants module for the [`u16` primitive type][u16].
 //!
 //! New code should use the associated constants directly on the primitive type.
 
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index fcf9707b74d..057053297cd 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -605,8 +605,6 @@ impl<T> Option<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(is_some_and)]
-    ///
     /// let x: Option<u32> = Some(2);
     /// assert_eq!(x.is_some_and(|x| x > 1), true);
     ///
@@ -618,7 +616,7 @@ impl<T> Option<T> {
     /// ```
     #[must_use]
     #[inline]
-    #[unstable(feature = "is_some_and", issue = "93050")]
+    #[stable(feature = "is_some_and", since = "CURRENT_RUSTC_VERSION")]
     pub fn is_some_and(self, f: impl FnOnce(T) -> bool) -> bool {
         match self {
             None => false,
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 76d9b0385d0..241602c0e18 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -545,8 +545,6 @@ impl<T, E> Result<T, E> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(is_some_and)]
-    ///
     /// let x: Result<u32, &str> = Ok(2);
     /// assert_eq!(x.is_ok_and(|x| x > 1), true);
     ///
@@ -558,7 +556,7 @@ impl<T, E> Result<T, E> {
     /// ```
     #[must_use]
     #[inline]
-    #[unstable(feature = "is_some_and", issue = "93050")]
+    #[stable(feature = "is_some_and", since = "CURRENT_RUSTC_VERSION")]
     pub fn is_ok_and(self, f: impl FnOnce(T) -> bool) -> bool {
         match self {
             Err(_) => false,
@@ -590,7 +588,6 @@ impl<T, E> Result<T, E> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(is_some_and)]
     /// use std::io::{Error, ErrorKind};
     ///
     /// let x: Result<u32, Error> = Err(Error::new(ErrorKind::NotFound, "!"));
@@ -604,7 +601,7 @@ impl<T, E> Result<T, E> {
     /// ```
     #[must_use]
     #[inline]
-    #[unstable(feature = "is_some_and", issue = "93050")]
+    #[stable(feature = "is_some_and", since = "CURRENT_RUSTC_VERSION")]
     pub fn is_err_and(self, f: impl FnOnce(E) -> bool) -> bool {
         match self {
             Ok(_) => false,
diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs
index 6acb937e784..14c455d4fa3 100644
--- a/library/std/src/io/buffered/bufwriter.rs
+++ b/library/std/src/io/buffered/bufwriter.rs
@@ -339,7 +339,7 @@ impl<W: Write> BufWriter<W> {
         let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) };
 
         // SAFETY: forget(self) prevents double dropping inner
-        let inner = unsafe { ptr::read(&mut self.inner) };
+        let inner = unsafe { ptr::read(&self.inner) };
         mem::forget(self);
 
         (inner, buf)
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 8c118b95b0a..736b3c0497c 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -289,7 +289,6 @@
 #![feature(hashmap_internals)]
 #![feature(ip)]
 #![feature(ip_in_core)]
-#![feature(is_some_and)]
 #![feature(maybe_uninit_slice)]
 #![feature(maybe_uninit_write_slice)]
 #![feature(panic_can_unwind)]
diff --git a/library/std/src/net/tcp.rs b/library/std/src/net/tcp.rs
index 3982d363661..4b42ad65ee6 100644
--- a/library/std/src/net/tcp.rs
+++ b/library/std/src/net/tcp.rs
@@ -869,7 +869,7 @@ impl TcpListener {
     /// use std::net::{TcpListener, TcpStream};
     ///
     /// fn listen_on(port: u16) -> impl Iterator<Item = TcpStream> {
-    ///     let listener = TcpListener::bind("127.0.0.1:80").unwrap();
+    ///     let listener = TcpListener::bind(("127.0.0.1", port)).unwrap();
     ///     listener.into_incoming()
     ///         .filter_map(Result::ok) /* Ignore failed connections */
     /// }
diff --git a/library/std/src/sys/common/thread_local/os_local.rs b/library/std/src/sys/common/thread_local/os_local.rs
index ce74ad3486e..1442a397e76 100644
--- a/library/std/src/sys/common/thread_local/os_local.rs
+++ b/library/std/src/sys/common/thread_local/os_local.rs
@@ -49,7 +49,9 @@ macro_rules! __thread_local_inner {
             #[inline]
             fn __init() -> $t { $init }
 
-            #[cfg_attr(not(bootstrap), inline)]
+            // `#[inline] does not work on windows-gnu due to linking errors around dllimports.
+            // See https://github.com/rust-lang/rust/issues/109797.
+            #[cfg_attr(not(windows), inline)]
             unsafe fn __getit(
                 init: $crate::option::Option<&mut $crate::option::Option<$t>>,
             ) -> $crate::option::Option<&'static $t> {
diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs
index 373157bd9e8..956db577d53 100644
--- a/library/std/src/sys/windows/fs.rs
+++ b/library/std/src/sys/windows/fs.rs
@@ -1403,24 +1403,40 @@ fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> {
     opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS);
     let f = File::open(junction, &opts)?;
     let h = f.as_inner().as_raw_handle();
-
     unsafe {
         let mut data = Align8([MaybeUninit::<u8>::uninit(); c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE]);
         let data_ptr = data.0.as_mut_ptr();
+        let data_end = data_ptr.add(c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
         let db = data_ptr.cast::<c::REPARSE_MOUNTPOINT_DATA_BUFFER>();
         // Zero the header to ensure it's fully initialized, including reserved parameters.
         *db = mem::zeroed();
-        let buf = ptr::addr_of_mut!((*db).ReparseTarget).cast::<c::WCHAR>();
-        let mut i = 0;
+        let reparse_target_slice = {
+            let buf_start = ptr::addr_of_mut!((*db).ReparseTarget).cast::<c::WCHAR>();
+            // Compute offset in bytes and then divide so that we round down
+            // rather than hit any UB (admittedly this arithmetic should work
+            // out so that this isn't necessary)
+            let buf_len_bytes = usize::try_from(data_end.byte_offset_from(buf_start)).unwrap();
+            let buf_len_wchars = buf_len_bytes / core::mem::size_of::<c::WCHAR>();
+            core::slice::from_raw_parts_mut(buf_start, buf_len_wchars)
+        };
+
         // FIXME: this conversion is very hacky
-        let v = br"\??\";
-        let v = v.iter().map(|x| *x as u16);
-        for c in v.chain(original.as_os_str().encode_wide()) {
-            *buf.add(i) = c;
+        let iter = br"\??\"
+            .iter()
+            .map(|x| *x as u16)
+            .chain(original.as_os_str().encode_wide())
+            .chain(core::iter::once(0));
+        let mut i = 0;
+        for c in iter {
+            if i >= reparse_target_slice.len() {
+                return Err(crate::io::const_io_error!(
+                    crate::io::ErrorKind::InvalidFilename,
+                    "Input filename is too long"
+                ));
+            }
+            reparse_target_slice[i] = c;
             i += 1;
         }
-        *buf.add(i) = 0;
-        i += 1;
         (*db).ReparseTag = c::IO_REPARSE_TAG_MOUNT_POINT;
         (*db).ReparseTargetMaximumLength = (i * 2) as c::WORD;
         (*db).ReparseTargetLength = ((i - 1) * 2) as c::WORD;
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 965dfa5f398..a158d1f718e 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -45,6 +45,7 @@ dependencies = [
  "hex",
  "ignore",
  "is-terminal",
+ "junction",
  "libc",
  "object",
  "once_cell",
@@ -350,6 +351,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
 
 [[package]]
+name = "junction"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca39ef0d69b18e6a2fd14c2f0a1d593200f4a4ed949b240b5917ab51fac754cb"
+dependencies = [
+ "scopeguard",
+ "winapi",
+]
+
+[[package]]
 name = "lazy_static"
 version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 2fbe7aa57aa..eeda6d7c121 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -61,6 +61,9 @@ sysinfo = { version = "0.26.0", optional = true }
 [target.'cfg(not(target_os = "solaris"))'.dependencies]
 fd-lock = "3.0.8"
 
+[target.'cfg(windows)'.dependencies.junction]
+version = "1.0.0"
+
 [target.'cfg(windows)'.dependencies.windows]
 version = "0.46.0"
 features = [
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index b8b6b7b2d4e..f038aceb34c 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -227,27 +227,36 @@ pub struct Config {
     pub reuse: Option<PathBuf>,
     pub cargo_native_static: bool,
     pub configure_args: Vec<String>,
+    pub out: PathBuf,
+    pub rust_info: channel::GitInfo,
 
     // These are either the stage0 downloaded binaries or the locally installed ones.
     pub initial_cargo: PathBuf,
     pub initial_rustc: PathBuf,
+
     #[cfg(not(test))]
     initial_rustfmt: RefCell<RustfmtState>,
     #[cfg(test)]
     pub initial_rustfmt: RefCell<RustfmtState>,
-    pub out: PathBuf,
-    pub rust_info: channel::GitInfo,
 }
 
 #[derive(Default, Deserialize)]
 #[cfg_attr(test, derive(Clone))]
 pub struct Stage0Metadata {
+    pub compiler: CompilerMetadata,
     pub config: Stage0Config,
     pub checksums_sha256: HashMap<String, String>,
     pub rustfmt: Option<RustfmtMetadata>,
 }
 #[derive(Default, Deserialize)]
 #[cfg_attr(test, derive(Clone))]
+pub struct CompilerMetadata {
+    pub date: String,
+    pub version: String,
+}
+
+#[derive(Default, Deserialize)]
+#[cfg_attr(test, derive(Clone))]
 pub struct Stage0Config {
     pub dist_server: String,
     pub artifacts_server: String,
@@ -1000,10 +1009,10 @@ impl Config {
             config.out = crate::util::absolute(&config.out);
         }
 
-        config.initial_rustc = build
-            .rustc
-            .map(PathBuf::from)
-            .unwrap_or_else(|| config.out.join(config.build.triple).join("stage0/bin/rustc"));
+        config.initial_rustc = build.rustc.map(PathBuf::from).unwrap_or_else(|| {
+            config.download_beta_toolchain();
+            config.out.join(config.build.triple).join("stage0/bin/rustc")
+        });
         config.initial_cargo = build
             .cargo
             .map(PathBuf::from)
diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs
index 5cea143e0a7..50569eb4f37 100644
--- a/src/bootstrap/config/tests.rs
+++ b/src/bootstrap/config/tests.rs
@@ -33,35 +33,58 @@ fn download_ci_llvm() {
     ));
 }
 
+// FIXME(ozkanonur): extend scope of the test
+// refs:
+//   - https://github.com/rust-lang/rust/issues/109120
+//   - https://github.com/rust-lang/rust/pull/109162#issuecomment-1496782487
 #[test]
 fn detect_src_and_out() {
-    let cfg = parse("");
+    fn test(cfg: Config, build_dir: Option<&str>) {
+        // This will bring absolute form of `src/bootstrap` path
+        let current_dir = std::env::current_dir().unwrap();
 
-    // This will bring absolute form of `src/bootstrap` path
-    let current_dir = std::env::current_dir().unwrap();
+        // get `src` by moving into project root path
+        let expected_src = current_dir.ancestors().nth(2).unwrap();
+        assert_eq!(&cfg.src, expected_src);
 
-    // get `src` by moving into project root path
-    let expected_src = current_dir.ancestors().nth(2).unwrap();
+        // Sanity check for `src`
+        let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
+        let expected_src = manifest_dir.ancestors().nth(2).unwrap();
+        assert_eq!(&cfg.src, expected_src);
 
-    assert_eq!(&cfg.src, expected_src);
+        // test if build-dir was manually given in config.toml
+        if let Some(custom_build_dir) = build_dir {
+            assert_eq!(&cfg.out, Path::new(custom_build_dir));
+        }
+        // test the native bootstrap way
+        else {
+            // This should bring output path of bootstrap in absolute form
+            let cargo_target_dir = env::var_os("CARGO_TARGET_DIR").expect(
+                "CARGO_TARGET_DIR must been provided for the test environment from bootstrap",
+            );
 
-    // This should bring output path of bootstrap in absolute form
-    let cargo_target_dir = env::var_os("CARGO_TARGET_DIR")
-        .expect("CARGO_TARGET_DIR must been provided for the test environment from bootstrap");
+            // Move to `build` from `build/bootstrap`
+            let expected_out = Path::new(&cargo_target_dir).parent().unwrap();
+            assert_eq!(&cfg.out, expected_out);
 
-    // Move to `build` from `build/bootstrap`
-    let expected_out = Path::new(&cargo_target_dir).parent().unwrap();
-    assert_eq!(&cfg.out, expected_out);
+            let args: Vec<String> = env::args().collect();
 
-    let args: Vec<String> = env::args().collect();
+            // Another test for `out` as a sanity check
+            //
+            // This will bring something similar to:
+            //     `{build-dir}/bootstrap/debug/deps/bootstrap-c7ee91d5661e2804`
+            // `{build-dir}` can be anywhere, not just in the rust project directory.
+            let dep = Path::new(args.first().unwrap());
+            let expected_out = dep.ancestors().nth(4).unwrap();
 
-    // Another test for `out` as a sanity check
-    //
-    // This will bring something similar to:
-    //     `{config_toml_place}/build/bootstrap/debug/deps/bootstrap-c7ee91d5661e2804`
-    // `{config_toml_place}` can be anywhere, not just in the rust project directory.
-    let dep = Path::new(args.first().unwrap());
-    let expected_out = dep.ancestors().nth(4).unwrap();
+            assert_eq!(&cfg.out, expected_out);
+        }
+    }
+
+    test(parse(""), None);
 
-    assert_eq!(&cfg.out, expected_out);
+    {
+        let build_dir = if cfg!(windows) { Some("C:\\tmp") } else { Some("/tmp") };
+        test(parse("build.build-dir = \"/tmp\""), build_dir);
+    }
 }
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index 8fbc034965a..24251556584 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -367,26 +367,70 @@ impl Config {
 
     pub(crate) fn download_ci_rustc(&self, commit: &str) {
         self.verbose(&format!("using downloaded stage2 artifacts from CI (commit {commit})"));
+
         let version = self.artifact_version_part(commit);
+        // download-rustc doesn't need its own cargo, it can just use beta's. But it does need the
+        // `rustc_private` crates for tools.
+        let extra_components = ["rustc-dev"];
+
+        self.download_toolchain(
+            &version,
+            "ci-rustc",
+            commit,
+            &extra_components,
+            Self::download_ci_component,
+        );
+    }
+
+    pub(crate) fn download_beta_toolchain(&self) {
+        self.verbose(&format!("downloading stage0 beta artifacts"));
+
+        let date = &self.stage0_metadata.compiler.date;
+        let version = &self.stage0_metadata.compiler.version;
+        let extra_components = ["cargo"];
+
+        let download_beta_component = |config: &Config, filename, prefix: &_, date: &_| {
+            config.download_component(DownloadSource::Dist, filename, prefix, date, "stage0")
+        };
+
+        self.download_toolchain(
+            version,
+            "stage0",
+            date,
+            &extra_components,
+            download_beta_component,
+        );
+    }
+
+    fn download_toolchain(
+        &self,
+        // FIXME(ozkanonur) use CompilerMetadata instead of `version: &str`
+        version: &str,
+        sysroot: &str,
+        stamp_key: &str,
+        extra_components: &[&str],
+        download_component: fn(&Config, String, &str, &str),
+    ) {
         let host = self.build.triple;
-        let bin_root = self.out.join(host).join("ci-rustc");
+        let bin_root = self.out.join(host).join(sysroot);
         let rustc_stamp = bin_root.join(".rustc-stamp");
 
-        if !bin_root.join("bin").join("rustc").exists() || program_out_of_date(&rustc_stamp, commit)
+        if !bin_root.join("bin").join(exe("rustc", self.build)).exists()
+            || program_out_of_date(&rustc_stamp, stamp_key)
         {
             if bin_root.exists() {
                 t!(fs::remove_dir_all(&bin_root));
             }
             let filename = format!("rust-std-{version}-{host}.tar.xz");
             let pattern = format!("rust-std-{host}");
-            self.download_ci_component(filename, &pattern, commit);
+            download_component(self, filename, &pattern, stamp_key);
             let filename = format!("rustc-{version}-{host}.tar.xz");
-            self.download_ci_component(filename, "rustc", commit);
-            // download-rustc doesn't need its own cargo, it can just use beta's.
-            let filename = format!("rustc-dev-{version}-{host}.tar.xz");
-            self.download_ci_component(filename, "rustc-dev", commit);
-            let filename = format!("rust-src-{version}.tar.xz");
-            self.download_ci_component(filename, "rust-src", commit);
+            download_component(self, filename, "rustc", stamp_key);
+
+            for component in extra_components {
+                let filename = format!("{component}-{version}-{host}.tar.xz");
+                download_component(self, filename, component, stamp_key);
+            }
 
             if self.should_fix_bins_and_dylibs() {
                 self.fix_bin_or_dylib(&bin_root.join("bin").join("rustc"));
@@ -403,7 +447,7 @@ impl Config {
                 }
             }
 
-            t!(fs::write(rustc_stamp, commit));
+            t!(fs::write(rustc_stamp, stamp_key));
         }
     }
 
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 84afddbf979..058ff429e80 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -1133,7 +1133,7 @@ impl Step for Tidy {
         if builder.config.channel == "dev" || builder.config.channel == "nightly" {
             builder.info("fmt check");
             if builder.initial_rustfmt().is_none() {
-                let inferred_rustfmt_dir = builder.config.initial_rustc.parent().unwrap();
+                let inferred_rustfmt_dir = builder.initial_rustc.parent().unwrap();
                 eprintln!(
                     "\
 error: no `rustfmt` binary found in {PATH}
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index 9a6aaffe22b..2e1adbf63bb 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -146,106 +146,9 @@ pub fn symlink_dir(config: &Config, src: &Path, dest: &Path) -> io::Result<()> {
         fs::symlink(src, dest)
     }
 
-    // Creating a directory junction on windows involves dealing with reparse
-    // points and the DeviceIoControl function, and this code is a skeleton of
-    // what can be found here:
-    //
-    // http://www.flexhex.com/docs/articles/hard-links.phtml
     #[cfg(windows)]
     fn symlink_dir_inner(target: &Path, junction: &Path) -> io::Result<()> {
-        use std::ffi::OsStr;
-        use std::os::windows::ffi::OsStrExt;
-
-        use windows::{
-            core::PCWSTR,
-            Win32::Foundation::{CloseHandle, HANDLE},
-            Win32::Storage::FileSystem::{
-                CreateFileW, FILE_ACCESS_FLAGS, FILE_FLAG_BACKUP_SEMANTICS,
-                FILE_FLAG_OPEN_REPARSE_POINT, FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE,
-                MAXIMUM_REPARSE_DATA_BUFFER_SIZE, OPEN_EXISTING,
-            },
-            Win32::System::Ioctl::FSCTL_SET_REPARSE_POINT,
-            Win32::System::SystemServices::{GENERIC_WRITE, IO_REPARSE_TAG_MOUNT_POINT},
-            Win32::System::IO::DeviceIoControl,
-        };
-
-        #[allow(non_snake_case)]
-        #[repr(C)]
-        struct REPARSE_MOUNTPOINT_DATA_BUFFER {
-            ReparseTag: u32,
-            ReparseDataLength: u32,
-            Reserved: u16,
-            ReparseTargetLength: u16,
-            ReparseTargetMaximumLength: u16,
-            Reserved1: u16,
-            ReparseTarget: u16,
-        }
-
-        fn to_u16s<S: AsRef<OsStr>>(s: S) -> io::Result<Vec<u16>> {
-            Ok(s.as_ref().encode_wide().chain(Some(0)).collect())
-        }
-
-        // We're using low-level APIs to create the junction, and these are more
-        // picky about paths. For example, forward slashes cannot be used as a
-        // path separator, so we should try to canonicalize the path first.
-        let target = fs::canonicalize(target)?;
-
-        fs::create_dir(junction)?;
-
-        let path = to_u16s(junction)?;
-
-        let h = unsafe {
-            CreateFileW(
-                PCWSTR(path.as_ptr()),
-                FILE_ACCESS_FLAGS(GENERIC_WRITE),
-                FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-                None,
-                OPEN_EXISTING,
-                FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
-                HANDLE::default(),
-            )
-        }
-        .map_err(|_| io::Error::last_os_error())?;
-
-        unsafe {
-            #[repr(C, align(8))]
-            struct Align8<T>(T);
-            let mut data = Align8([0u8; MAXIMUM_REPARSE_DATA_BUFFER_SIZE as usize]);
-            let db = data.0.as_mut_ptr() as *mut REPARSE_MOUNTPOINT_DATA_BUFFER;
-            let buf = core::ptr::addr_of_mut!((*db).ReparseTarget) as *mut u16;
-            let mut i = 0;
-            // FIXME: this conversion is very hacky
-            let v = br"\??\";
-            let v = v.iter().map(|x| *x as u16);
-            for c in v.chain(target.as_os_str().encode_wide().skip(4)) {
-                *buf.offset(i) = c;
-                i += 1;
-            }
-            *buf.offset(i) = 0;
-            i += 1;
-
-            (*db).ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
-            (*db).ReparseTargetMaximumLength = (i * 2) as u16;
-            (*db).ReparseTargetLength = ((i - 1) * 2) as u16;
-            (*db).ReparseDataLength = ((*db).ReparseTargetLength + 12) as u32;
-
-            let mut ret = 0u32;
-            DeviceIoControl(
-                h,
-                FSCTL_SET_REPARSE_POINT,
-                Some(db.cast()),
-                (*db).ReparseDataLength + 8,
-                None,
-                0,
-                Some(&mut ret),
-                None,
-            )
-            .ok()
-            .map_err(|_| io::Error::last_os_error())?;
-        }
-
-        unsafe { CloseHandle(h) };
-        Ok(())
+        junction::create(&target, &junction)
     }
 }
 
diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index 960c1de1782..ae180439d23 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -38,6 +38,15 @@ future.
 Attempting to use these error numbers on stable will result in the code sample being interpreted as
 plain text.
 
+### `missing_doc_code_examples` lint
+
+This lint will emit a warning if an item doesn't have a code example in its documentation.
+It can be enabled using:
+
+```rust,ignore (nightly)
+#![deny(rustdoc::missing_doc_code_examples)]
+```
+
 ## Extensions to the `#[doc]` attribute
 
 These features operate by extending the `#[doc]` attribute, and thus can be caught by the compiler
diff --git a/src/doc/rustdoc/src/write-documentation/what-to-include.md b/src/doc/rustdoc/src/write-documentation/what-to-include.md
index cf1e6a8d3ca..16457ed0ff8 100644
--- a/src/doc/rustdoc/src/write-documentation/what-to-include.md
+++ b/src/doc/rustdoc/src/write-documentation/what-to-include.md
@@ -39,9 +39,7 @@ warning: 1 warning emitted
 As a library author, adding the lint `#![deny(missing_docs)]` is a great way to
 ensure the project does not drift away from being documented well, and
 `#![warn(missing_docs)]` is a good way to move towards comprehensive
-documentation.  In addition to docs, `#![deny(rustdoc::missing_doc_code_examples)]`
-ensures each function contains a usage example.  In our example above, the
-warning is resolved by adding crate level documentation.
+documentation.
 
 There are more lints in the upcoming chapter [Lints][rustdoc-lints].
 
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 02b358e863b..7a2449cbe9a 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -136,10 +136,6 @@ impl Buffer {
         self.into_inner()
     }
 
-    pub(crate) fn is_for_html(&self) -> bool {
-        self.for_html
-    }
-
     pub(crate) fn reserve(&mut self, additional: usize) {
         self.buffer.reserve(additional)
     }
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index d75d03071f8..1e3cd266850 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -50,6 +50,7 @@ use std::string::ToString;
 use askama::Template;
 use rustc_ast_pretty::pprust;
 use rustc_attr::{ConstStability, Deprecation, StabilityLevel};
+use rustc_data_structures::captures::Captures;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_hir::def_id::{DefId, DefIdSet};
 use rustc_hir::Mutability;
@@ -69,7 +70,7 @@ use crate::formats::item_type::ItemType;
 use crate::formats::{AssocItemRender, Impl, RenderMode};
 use crate::html::escape::Escape;
 use crate::html::format::{
-    href, join_with_double_colon, print_abi_with_space, print_constness_with_space,
+    display_fn, href, join_with_double_colon, print_abi_with_space, print_constness_with_space,
     print_default_space, print_generic_bounds, print_where_clause, visibility_print_with_space,
     Buffer, Ending, HrefError, PrintWithSpace,
 };
@@ -408,128 +409,134 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String {
     )
 }
 
-fn document(
-    w: &mut Buffer,
-    cx: &mut Context<'_>,
-    item: &clean::Item,
-    parent: Option<&clean::Item>,
+fn document<'a, 'cx: 'a>(
+    cx: &'a mut Context<'cx>,
+    item: &'a clean::Item,
+    parent: Option<&'a clean::Item>,
     heading_offset: HeadingOffset,
-) {
+) -> impl fmt::Display + 'a + Captures<'cx> {
     if let Some(ref name) = item.name {
         info!("Documenting {}", name);
     }
-    document_item_info(cx, item, parent).render_into(w).unwrap();
-    if parent.is_none() {
-        document_full_collapsible(w, item, cx, heading_offset);
-    } else {
-        document_full(w, item, cx, heading_offset);
-    }
+
+    display_fn(move |f| {
+        document_item_info(cx, item, parent).render_into(f).unwrap();
+        if parent.is_none() {
+            write!(f, "{}", document_full_collapsible(item, cx, heading_offset))?;
+        } else {
+            write!(f, "{}", document_full(item, cx, heading_offset))?;
+        }
+        Ok(())
+    })
 }
 
 /// Render md_text as markdown.
-fn render_markdown(
-    w: &mut Buffer,
-    cx: &mut Context<'_>,
-    md_text: &str,
+fn render_markdown<'a, 'cx: 'a>(
+    cx: &'a mut Context<'cx>,
+    md_text: &'a str,
     links: Vec<RenderedLink>,
     heading_offset: HeadingOffset,
-) {
-    write!(
-        w,
-        "<div class=\"docblock\">{}</div>",
-        Markdown {
-            content: md_text,
-            links: &links,
-            ids: &mut cx.id_map,
-            error_codes: cx.shared.codes,
-            edition: cx.shared.edition(),
-            playground: &cx.shared.playground,
-            heading_offset,
-        }
-        .into_string()
-    )
+) -> impl fmt::Display + 'a + Captures<'cx> {
+    display_fn(move |f| {
+        write!(
+            f,
+            "<div class=\"docblock\">{}</div>",
+            Markdown {
+                content: md_text,
+                links: &links,
+                ids: &mut cx.id_map,
+                error_codes: cx.shared.codes,
+                edition: cx.shared.edition(),
+                playground: &cx.shared.playground,
+                heading_offset,
+            }
+            .into_string()
+        )
+    })
 }
 
 /// Writes a documentation block containing only the first paragraph of the documentation. If the
 /// docs are longer, a "Read more" link is appended to the end.
-fn document_short(
-    w: &mut Buffer,
-    item: &clean::Item,
-    cx: &mut Context<'_>,
-    link: AssocItemLink<'_>,
-    parent: &clean::Item,
+fn document_short<'a, 'cx: 'a>(
+    item: &'a clean::Item,
+    cx: &'a mut Context<'cx>,
+    link: AssocItemLink<'a>,
+    parent: &'a clean::Item,
     show_def_docs: bool,
-) {
-    document_item_info(cx, item, Some(parent)).render_into(w).unwrap();
-    if !show_def_docs {
-        return;
-    }
-    if let Some(s) = item.doc_value() {
-        let (mut summary_html, has_more_content) =
-            MarkdownSummaryLine(&s, &item.links(cx)).into_string_with_has_more_content();
+) -> impl fmt::Display + 'a + Captures<'cx> {
+    display_fn(move |f| {
+        document_item_info(cx, item, Some(parent)).render_into(f).unwrap();
+        if !show_def_docs {
+            return Ok(());
+        }
+        if let Some(s) = item.doc_value() {
+            let (mut summary_html, has_more_content) =
+                MarkdownSummaryLine(&s, &item.links(cx)).into_string_with_has_more_content();
 
-        if has_more_content {
-            let link = format!(r#" <a{}>Read more</a>"#, assoc_href_attr(item, link, cx));
+            if has_more_content {
+                let link = format!(r#" <a{}>Read more</a>"#, assoc_href_attr(item, link, cx));
 
-            if let Some(idx) = summary_html.rfind("</p>") {
-                summary_html.insert_str(idx, &link);
-            } else {
-                summary_html.push_str(&link);
+                if let Some(idx) = summary_html.rfind("</p>") {
+                    summary_html.insert_str(idx, &link);
+                } else {
+                    summary_html.push_str(&link);
+                }
             }
-        }
 
-        write!(w, "<div class='docblock'>{}</div>", summary_html,);
-    }
+            write!(f, "<div class='docblock'>{}</div>", summary_html)?;
+        }
+        Ok(())
+    })
 }
 
-fn document_full_collapsible(
-    w: &mut Buffer,
-    item: &clean::Item,
-    cx: &mut Context<'_>,
+fn document_full_collapsible<'a, 'cx: 'a>(
+    item: &'a clean::Item,
+    cx: &'a mut Context<'cx>,
     heading_offset: HeadingOffset,
-) {
-    document_full_inner(w, item, cx, true, heading_offset);
+) -> impl fmt::Display + 'a + Captures<'cx> {
+    document_full_inner(item, cx, true, heading_offset)
 }
 
-fn document_full(
-    w: &mut Buffer,
-    item: &clean::Item,
-    cx: &mut Context<'_>,
+fn document_full<'a, 'cx: 'a>(
+    item: &'a clean::Item,
+    cx: &'a mut Context<'cx>,
     heading_offset: HeadingOffset,
-) {
-    document_full_inner(w, item, cx, false, heading_offset);
+) -> impl fmt::Display + 'a + Captures<'cx> {
+    document_full_inner(item, cx, false, heading_offset)
 }
 
-fn document_full_inner(
-    w: &mut Buffer,
-    item: &clean::Item,
-    cx: &mut Context<'_>,
+fn document_full_inner<'a, 'cx: 'a>(
+    item: &'a clean::Item,
+    cx: &'a mut Context<'cx>,
     is_collapsible: bool,
     heading_offset: HeadingOffset,
-) {
-    if let Some(s) = item.collapsed_doc_value() {
-        debug!("Doc block: =====\n{}\n=====", s);
-        if is_collapsible {
-            w.write_str(
-                "<details class=\"toggle top-doc\" open>\
-                <summary class=\"hideme\">\
-                     <span>Expand description</span>\
-                </summary>",
-            );
-            render_markdown(w, cx, &s, item.links(cx), heading_offset);
-            w.write_str("</details>");
-        } else {
-            render_markdown(w, cx, &s, item.links(cx), heading_offset);
+) -> impl fmt::Display + 'a + Captures<'cx> {
+    display_fn(move |f| {
+        if let Some(s) = item.collapsed_doc_value() {
+            debug!("Doc block: =====\n{}\n=====", s);
+            if is_collapsible {
+                write!(
+                    f,
+                    "<details class=\"toggle top-doc\" open>\
+                    <summary class=\"hideme\">\
+                        <span>Expand description</span>\
+                    </summary>{}</details>",
+                    render_markdown(cx, &s, item.links(cx), heading_offset)
+                )?;
+            } else {
+                write!(f, "{}", render_markdown(cx, &s, item.links(cx), heading_offset))?;
+            }
         }
-    }
 
-    let kind = match &*item.kind {
-        clean::ItemKind::StrippedItem(box kind) | kind => kind,
-    };
+        let kind = match &*item.kind {
+            clean::ItemKind::StrippedItem(box kind) | kind => kind,
+        };
 
-    if let clean::ItemKind::FunctionItem(..) | clean::ItemKind::MethodItem(..) = kind {
-        render_call_locations(w, cx, item);
-    }
+        if let clean::ItemKind::FunctionItem(..) | clean::ItemKind::MethodItem(..) = kind {
+            render_call_locations(f, cx, item);
+        }
+        Ok(())
+    })
 }
 
 #[derive(Template)]
@@ -653,7 +660,7 @@ fn short_item_info(
 // "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages).
 pub(crate) fn render_impls(
     cx: &mut Context<'_>,
-    w: &mut Buffer,
+    mut w: impl Write,
     impls: &[&Impl],
     containing_item: &clean::Item,
     toggle_open_by_default: bool,
@@ -665,7 +672,7 @@ pub(crate) fn render_impls(
             let did = i.trait_did().unwrap();
             let provided_trait_methods = i.inner_impl().provided_trait_methods(tcx);
             let assoc_link = AssocItemLink::GotoSource(did.into(), &provided_trait_methods);
-            let mut buffer = if w.is_for_html() { Buffer::html() } else { Buffer::new() };
+            let mut buffer = Buffer::new();
             render_impl(
                 &mut buffer,
                 cx,
@@ -686,7 +693,7 @@ pub(crate) fn render_impls(
         })
         .collect::<Vec<_>>();
     rendered_impls.sort();
-    w.write_str(&rendered_impls.join(""));
+    w.write_str(&rendered_impls.join("")).unwrap();
 }
 
 /// Build a (possibly empty) `href` attribute (a key-value pair) for the given associated item.
@@ -842,7 +849,7 @@ fn assoc_method(
     let (indent, indent_str, end_newline) = if parent == ItemType::Trait {
         header_len += 4;
         let indent_str = "    ";
-        render_attributes_in_pre(w, meth, indent_str);
+        write!(w, "{}", render_attributes_in_pre(meth, indent_str));
         (4, indent_str, Ending::NoNewline)
     } else {
         render_attributes_in_code(w, meth);
@@ -1038,10 +1045,16 @@ fn attributes(it: &clean::Item) -> Vec<String> {
 
 // When an attribute is rendered inside a `<pre>` tag, it is formatted using
 // a whitespace prefix and newline.
-fn render_attributes_in_pre(w: &mut Buffer, it: &clean::Item, prefix: &str) {
-    for a in attributes(it) {
-        writeln!(w, "{}{}", prefix, a);
-    }
+fn render_attributes_in_pre<'a>(
+    it: &'a clean::Item,
+    prefix: &'a str,
+) -> impl fmt::Display + Captures<'a> {
+    crate::html::format::display_fn(move |f| {
+        for a in attributes(it) {
+            writeln!(f, "{}{}", prefix, a)?;
+        }
+        Ok(())
+    })
 }
 
 // When an attribute is rendered inside a <code> tag, it is formatted using
@@ -1067,61 +1080,68 @@ impl<'a> AssocItemLink<'a> {
     }
 }
 
-fn write_impl_section_heading(w: &mut Buffer, title: &str, id: &str) {
+fn write_impl_section_heading(mut w: impl fmt::Write, title: &str, id: &str) {
     write!(
         w,
         "<h2 id=\"{id}\" class=\"small-section-header\">\
             {title}\
             <a href=\"#{id}\" class=\"anchor\">§</a>\
          </h2>"
-    );
+    )
+    .unwrap();
 }
 
 pub(crate) fn render_all_impls(
-    w: &mut Buffer,
+    mut w: impl Write,
     cx: &mut Context<'_>,
     containing_item: &clean::Item,
     concrete: &[&Impl],
     synthetic: &[&Impl],
     blanket_impl: &[&Impl],
 ) {
-    let mut impls = Buffer::empty_from(w);
+    let mut impls = Buffer::html();
     render_impls(cx, &mut impls, concrete, containing_item, true);
     let impls = impls.into_inner();
     if !impls.is_empty() {
-        write_impl_section_heading(w, "Trait Implementations", "trait-implementations");
-        write!(w, "<div id=\"trait-implementations-list\">{}</div>", impls);
+        write_impl_section_heading(&mut w, "Trait Implementations", "trait-implementations");
+        write!(w, "<div id=\"trait-implementations-list\">{}</div>", impls).unwrap();
     }
 
     if !synthetic.is_empty() {
-        write_impl_section_heading(w, "Auto Trait Implementations", "synthetic-implementations");
-        w.write_str("<div id=\"synthetic-implementations-list\">");
-        render_impls(cx, w, synthetic, containing_item, false);
-        w.write_str("</div>");
+        write_impl_section_heading(
+            &mut w,
+            "Auto Trait Implementations",
+            "synthetic-implementations",
+        );
+        w.write_str("<div id=\"synthetic-implementations-list\">").unwrap();
+        render_impls(cx, &mut w, synthetic, containing_item, false);
+        w.write_str("</div>").unwrap();
     }
 
     if !blanket_impl.is_empty() {
-        write_impl_section_heading(w, "Blanket Implementations", "blanket-implementations");
-        w.write_str("<div id=\"blanket-implementations-list\">");
-        render_impls(cx, w, blanket_impl, containing_item, false);
-        w.write_str("</div>");
+        write_impl_section_heading(&mut w, "Blanket Implementations", "blanket-implementations");
+        w.write_str("<div id=\"blanket-implementations-list\">").unwrap();
+        render_impls(cx, &mut w, blanket_impl, containing_item, false);
+        w.write_str("</div>").unwrap();
     }
 }
 
-fn render_assoc_items(
-    w: &mut Buffer,
-    cx: &mut Context<'_>,
-    containing_item: &clean::Item,
+fn render_assoc_items<'a, 'cx: 'a>(
+    cx: &'a mut Context<'cx>,
+    containing_item: &'a clean::Item,
     it: DefId,
-    what: AssocItemRender<'_>,
-) {
+    what: AssocItemRender<'a>,
+) -> impl fmt::Display + 'a + Captures<'cx> {
     let mut derefs = DefIdSet::default();
     derefs.insert(it);
-    render_assoc_items_inner(w, cx, containing_item, it, what, &mut derefs)
+    display_fn(move |f| {
+        render_assoc_items_inner(f, cx, containing_item, it, what, &mut derefs);
+        Ok(())
+    })
 }
 
 fn render_assoc_items_inner(
-    w: &mut Buffer,
+    mut w: &mut dyn fmt::Write,
     cx: &mut Context<'_>,
     containing_item: &clean::Item,
     it: DefId,
@@ -1134,7 +1154,7 @@ fn render_assoc_items_inner(
     let Some(v) = cache.impls.get(&it) else { return };
     let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none());
     if !non_trait.is_empty() {
-        let mut tmp_buf = Buffer::empty_from(w);
+        let mut tmp_buf = Buffer::html();
         let (render_mode, id) = match what {
             AssocItemRender::All => {
                 write_impl_section_heading(&mut tmp_buf, "Implementations", "implementations");
@@ -1158,7 +1178,7 @@ fn render_assoc_items_inner(
                 (RenderMode::ForDeref { mut_: deref_mut_ }, cx.derive_id(id))
             }
         };
-        let mut impls_buf = Buffer::empty_from(w);
+        let mut impls_buf = Buffer::html();
         for i in &non_trait {
             render_impl(
                 &mut impls_buf,
@@ -1178,10 +1198,10 @@ fn render_assoc_items_inner(
             );
         }
         if !impls_buf.is_empty() {
-            w.push_buffer(tmp_buf);
-            write!(w, "<div id=\"{}\">", id);
-            w.push_buffer(impls_buf);
-            w.write_str("</div>");
+            write!(w, "{}", tmp_buf.into_inner()).unwrap();
+            write!(w, "<div id=\"{}\">", id).unwrap();
+            write!(w, "{}", impls_buf.into_inner()).unwrap();
+            w.write_str("</div>").unwrap();
         }
     }
 
@@ -1191,7 +1211,7 @@ fn render_assoc_items_inner(
         if let Some(impl_) = deref_impl {
             let has_deref_mut =
                 traits.iter().any(|t| t.trait_did() == cx.tcx().lang_items().deref_mut_trait());
-            render_deref_methods(w, cx, impl_, containing_item, has_deref_mut, derefs);
+            render_deref_methods(&mut w, cx, impl_, containing_item, has_deref_mut, derefs);
         }
 
         // If we were already one level into rendering deref methods, we don't want to render
@@ -1210,7 +1230,7 @@ fn render_assoc_items_inner(
 }
 
 fn render_deref_methods(
-    w: &mut Buffer,
+    mut w: impl Write,
     cx: &mut Context<'_>,
     impl_: &Impl,
     container_item: &clean::Item,
@@ -1242,10 +1262,10 @@ fn render_deref_methods(
                 return;
             }
         }
-        render_assoc_items_inner(w, cx, container_item, did, what, derefs);
+        render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs);
     } else if let Some(prim) = target.primitive_type() {
         if let Some(&did) = cache.primitive_locations.get(&prim) {
-            render_assoc_items_inner(w, cx, container_item, did, what, derefs);
+            render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs);
         }
     }
 }
@@ -1478,18 +1498,25 @@ fn render_impl(
                             document_item_info(cx, it, Some(parent))
                                 .render_into(&mut info_buffer)
                                 .unwrap();
-                            document_full(&mut doc_buffer, item, cx, HeadingOffset::H5);
+                            write!(
+                                &mut doc_buffer,
+                                "{}",
+                                document_full(item, cx, HeadingOffset::H5)
+                            );
                             short_documented = false;
                         } else {
                             // In case the item isn't documented,
                             // provide short documentation from the trait.
-                            document_short(
+                            write!(
                                 &mut doc_buffer,
-                                it,
-                                cx,
-                                link,
-                                parent,
-                                rendering_params.show_def_docs,
+                                "{}",
+                                document_short(
+                                    it,
+                                    cx,
+                                    link,
+                                    parent,
+                                    rendering_params.show_def_docs,
+                                )
                             );
                         }
                     }
@@ -1498,18 +1525,15 @@ fn render_impl(
                         .render_into(&mut info_buffer)
                         .unwrap();
                     if rendering_params.show_def_docs {
-                        document_full(&mut doc_buffer, item, cx, HeadingOffset::H5);
+                        write!(&mut doc_buffer, "{}", document_full(item, cx, HeadingOffset::H5));
                         short_documented = false;
                     }
                 }
             } else {
-                document_short(
+                write!(
                     &mut doc_buffer,
-                    item,
-                    cx,
-                    link,
-                    parent,
-                    rendering_params.show_def_docs,
+                    "{}",
+                    document_short(item, cx, link, parent, rendering_params.show_def_docs,)
                 );
             }
         }
@@ -2206,7 +2230,7 @@ const MAX_FULL_EXAMPLES: usize = 5;
 const NUM_VISIBLE_LINES: usize = 10;
 
 /// Generates the HTML for example call locations generated via the --scrape-examples flag.
-fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item) {
+fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &clean::Item) {
     let tcx = cx.tcx();
     let def_id = item.item_id.expect_def_id();
     let key = tcx.def_path_hash(def_id);
@@ -2215,7 +2239,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
     // Generate a unique ID so users can link to this section for a given method
     let id = cx.id_map.derive("scraped-examples");
     write!(
-        w,
+        &mut w,
         "<div class=\"docblock scraped-example-list\">\
           <span></span>\
           <h5 id=\"{id}\">\
@@ -2224,7 +2248,8 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
           </h5>",
         root_path = cx.root_path(),
         id = id
-    );
+    )
+    .unwrap();
 
     // Create a URL to a particular location in a reverse-dependency's source file
     let link_to_loc = |call_data: &CallData, loc: &CallLocation| -> (String, String) {
@@ -2242,7 +2267,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
     };
 
     // Generate the HTML for a single example, being the title and code block
-    let write_example = |w: &mut Buffer, (path, call_data): (&PathBuf, &CallData)| -> bool {
+    let write_example = |mut w: &mut W, (path, call_data): (&PathBuf, &CallData)| -> bool {
         let contents = match fs::read_to_string(&path) {
             Ok(contents) => contents,
             Err(err) => {
@@ -2290,7 +2315,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
         let locations_encoded = serde_json::to_string(&line_ranges).unwrap();
 
         write!(
-            w,
+            &mut w,
             "<div class=\"scraped-example {expanded_cls}\" data-locs=\"{locations}\">\
                 <div class=\"scraped-example-title\">\
                    {name} (<a href=\"{url}\">{title}</a>)\
@@ -2303,10 +2328,12 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
             // The locations are encoded as a data attribute, so they can be read
             // later by the JS for interactions.
             locations = Escape(&locations_encoded)
-        );
+        )
+        .unwrap();
 
         if line_ranges.len() > 1 {
-            write!(w, r#"<button class="prev">&pr;</button> <button class="next">&sc;</button>"#);
+            write!(w, r#"<button class="prev">&pr;</button> <button class="next">&sc;</button>"#)
+                .unwrap();
         }
 
         // Look for the example file in the source map if it exists, otherwise return a dummy span
@@ -2333,7 +2360,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
         decoration_info.insert("highlight", byte_ranges);
 
         sources::print_src(
-            w,
+            &mut w,
             contents_subset,
             file_span,
             cx,
@@ -2341,7 +2368,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
             highlight::DecorationInfo(decoration_info),
             sources::SourceContext::Embedded { offset: line_min, needs_expansion },
         );
-        write!(w, "</div></div>");
+        write!(w, "</div></div>").unwrap();
 
         true
     };
@@ -2375,7 +2402,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
 
     // An example may fail to write if its source can't be read for some reason, so this method
     // continues iterating until a write succeeds
-    let write_and_skip_failure = |w: &mut Buffer, it: &mut Peekable<_>| {
+    let write_and_skip_failure = |w: &mut W, it: &mut Peekable<_>| {
         while let Some(example) = it.next() {
             if write_example(&mut *w, example) {
                 break;
@@ -2384,7 +2411,7 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
     };
 
     // Write just one example that's visible by default in the method's description.
-    write_and_skip_failure(w, &mut it);
+    write_and_skip_failure(&mut w, &mut it);
 
     // Then add the remaining examples in a hidden section.
     if it.peek().is_some() {
@@ -2397,17 +2424,19 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
                   <div class=\"hide-more\">Hide additional examples</div>\
                   <div class=\"more-scraped-examples\">\
                     <div class=\"toggle-line\"><div class=\"toggle-line-inner\"></div></div>"
-        );
+        )
+        .unwrap();
 
         // Only generate inline code for MAX_FULL_EXAMPLES number of examples. Otherwise we could
         // make the page arbitrarily huge!
         for _ in 0..MAX_FULL_EXAMPLES {
-            write_and_skip_failure(w, &mut it);
+            write_and_skip_failure(&mut w, &mut it);
         }
 
         // For the remaining examples, generate a <ul> containing links to the source files.
         if it.peek().is_some() {
-            write!(w, r#"<div class="example-links">Additional examples can be found in:<br><ul>"#);
+            write!(w, r#"<div class="example-links">Additional examples can be found in:<br><ul>"#)
+                .unwrap();
             it.for_each(|(_, call_data)| {
                 let (url, _) = link_to_loc(call_data, &call_data.locations[0]);
                 write!(
@@ -2415,13 +2444,14 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
                     r#"<li><a href="{url}">{name}</a></li>"#,
                     url = url,
                     name = call_data.display_name
-                );
+                )
+                .unwrap();
             });
-            write!(w, "</ul></div>");
+            write!(w, "</ul></div>").unwrap();
         }
 
-        write!(w, "</div></details>");
+        write!(w, "</div></details>").unwrap();
     }
 
-    write!(w, "</div>");
+    write!(w, "</div>").unwrap();
 }
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 674cd0d62d4..6bce5734004 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -202,7 +202,7 @@ fn should_hide_fields(n_fields: usize) -> bool {
     n_fields > 12
 }
 
-fn toggle_open(w: &mut Buffer, text: impl fmt::Display) {
+fn toggle_open(mut w: impl fmt::Write, text: impl fmt::Display) {
     write!(
         w,
         "<details class=\"toggle type-contents-toggle\">\
@@ -210,15 +210,16 @@ fn toggle_open(w: &mut Buffer, text: impl fmt::Display) {
                 <span>Show {}</span>\
             </summary>",
         text
-    );
+    )
+    .unwrap();
 }
 
-fn toggle_close(w: &mut Buffer) {
-    w.write_str("</details>");
+fn toggle_close(mut w: impl fmt::Write) {
+    w.write_str("</details>").unwrap();
 }
 
 fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items: &[clean::Item]) {
-    document(w, cx, item, None, HeadingOffset::H2);
+    write!(w, "{}", document(cx, item, None, HeadingOffset::H2));
 
     let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped()).collect::<Vec<usize>>();
 
@@ -544,12 +545,12 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle
         f.decl.output.as_return().and_then(|output| notable_traits_button(output, cx));
 
     wrap_item(w, |w| {
-        render_attributes_in_pre(w, it, "");
         w.reserve(header_len);
         write!(
             w,
-            "{vis}{constness}{asyncness}{unsafety}{abi}fn \
+            "{attrs}{vis}{constness}{asyncness}{unsafety}{abi}fn \
                 {name}{generics}{decl}{notable_traits}{where_clause}",
+            attrs = render_attributes_in_pre(it, ""),
             vis = visibility,
             constness = constness,
             asyncness = asyncness,
@@ -562,7 +563,7 @@ fn item_function(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, f: &cle
             notable_traits = notable_traits.unwrap_or_default(),
         );
     });
-    document(w, cx, it, None, HeadingOffset::H2);
+    write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
 }
 
 fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Trait) {
@@ -580,17 +581,17 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
     let must_implement_one_of_functions = tcx.trait_def(t.def_id).must_implement_one_of.clone();
 
     // Output the trait definition
-    wrap_item(w, |w| {
-        render_attributes_in_pre(w, it, "");
+    wrap_item(w, |mut w| {
         write!(
             w,
-            "{}{}{}trait {}{}{}",
+            "{attrs}{}{}{}trait {}{}{}",
             visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
             t.unsafety(tcx).print_with_space(),
             if t.is_auto(tcx) { "auto " } else { "" },
             it.name.unwrap(),
             t.generics.print(cx),
-            bounds
+            bounds,
+            attrs = render_attributes_in_pre(it, ""),
         );
 
         if !t.generics.where_predicates.is_empty() {
@@ -610,7 +611,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
             if should_hide_fields(count_types) {
                 toggle = true;
                 toggle_open(
-                    w,
+                    &mut w,
                     format_args!("{} associated items", count_types + count_consts + count_methods),
                 );
             }
@@ -634,7 +635,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
             if !toggle && should_hide_fields(count_types + count_consts) {
                 toggle = true;
                 toggle_open(
-                    w,
+                    &mut w,
                     format_args!(
                         "{} associated constant{} and {} method{}",
                         count_consts,
@@ -662,7 +663,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
             }
             if !toggle && should_hide_fields(count_methods) {
                 toggle = true;
-                toggle_open(w, format_args!("{} methods", count_methods));
+                toggle_open(&mut w, format_args!("{} methods", count_methods));
             }
             if count_consts != 0 && count_methods != 0 {
                 w.write_str("\n");
@@ -710,14 +711,14 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
                 }
             }
             if toggle {
-                toggle_close(w);
+                toggle_close(&mut w);
             }
             w.write_str("}");
         }
     });
 
     // Trait documentation
-    document(w, cx, it, None, HeadingOffset::H2);
+    write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
 
     fn write_small_section_header(w: &mut Buffer, id: &str, title: &str, extra_content: &str) {
         write!(
@@ -735,7 +736,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
         let item_type = m.type_();
         let id = cx.derive_id(format!("{}.{}", item_type, name));
         let mut content = Buffer::empty_from(w);
-        document(&mut content, cx, m, Some(t), HeadingOffset::H5);
+        write!(&mut content, "{}", document(cx, m, Some(t), HeadingOffset::H5));
         let toggled = !content.is_empty();
         if toggled {
             let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
@@ -847,7 +848,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
     }
 
     // If there are methods directly on this trait object, render them here.
-    render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All);
+    write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All));
 
     let cloned_shared = Rc::clone(&cx.shared);
     let cache = &cloned_shared.cache;
@@ -1057,147 +1058,201 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
 
 fn item_trait_alias(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::TraitAlias) {
     wrap_item(w, |w| {
-        render_attributes_in_pre(w, it, "");
         write!(
             w,
-            "trait {}{}{} = {};",
+            "{attrs}trait {}{}{} = {};",
             it.name.unwrap(),
             t.generics.print(cx),
             print_where_clause(&t.generics, cx, 0, Ending::Newline),
-            bounds(&t.bounds, true, cx)
+            bounds(&t.bounds, true, cx),
+            attrs = render_attributes_in_pre(it, ""),
         );
     });
 
-    document(w, cx, it, None, HeadingOffset::H2);
+    write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
 
     // Render any items associated directly to this alias, as otherwise they
     // won't be visible anywhere in the docs. It would be nice to also show
     // associated items from the aliased type (see discussion in #32077), but
     // we need #14072 to make sense of the generics.
-    render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
+    write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All))
 }
 
 fn item_opaque_ty(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) {
     wrap_item(w, |w| {
-        render_attributes_in_pre(w, it, "");
         write!(
             w,
-            "type {}{}{where_clause} = impl {bounds};",
+            "{attrs}type {}{}{where_clause} = impl {bounds};",
             it.name.unwrap(),
             t.generics.print(cx),
             where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline),
             bounds = bounds(&t.bounds, false, cx),
+            attrs = render_attributes_in_pre(it, ""),
         );
     });
 
-    document(w, cx, it, None, HeadingOffset::H2);
+    write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
 
     // Render any items associated directly to this alias, as otherwise they
     // won't be visible anywhere in the docs. It would be nice to also show
     // associated items from the aliased type (see discussion in #32077), but
     // we need #14072 to make sense of the generics.
-    render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
+    write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All))
 }
 
 fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Typedef) {
     fn write_content(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) {
         wrap_item(w, |w| {
-            render_attributes_in_pre(w, it, "");
             write!(
                 w,
-                "{}type {}{}{where_clause} = {type_};",
+                "{attrs}{}type {}{}{where_clause} = {type_};",
                 visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
                 it.name.unwrap(),
                 t.generics.print(cx),
                 where_clause = print_where_clause(&t.generics, cx, 0, Ending::Newline),
                 type_ = t.type_.print(cx),
+                attrs = render_attributes_in_pre(it, ""),
             );
         });
     }
 
     write_content(w, cx, it, t);
 
-    document(w, cx, it, None, HeadingOffset::H2);
+    write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
 
     let def_id = it.item_id.expect_def_id();
     // Render any items associated directly to this alias, as otherwise they
     // won't be visible anywhere in the docs. It would be nice to also show
     // associated items from the aliased type (see discussion in #32077), but
     // we need #14072 to make sense of the generics.
-    render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
-    document_type_layout(w, cx, def_id);
+    write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All));
+    write!(w, "{}", document_type_layout(cx, def_id));
 }
 
 fn item_union(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Union) {
-    wrap_item(w, |w| {
-        render_attributes_in_pre(w, it, "");
-        render_union(w, it, Some(&s.generics), &s.fields, cx);
-    });
+    #[derive(Template)]
+    #[template(path = "item_union.html")]
+    struct ItemUnion<'a, 'cx> {
+        cx: std::cell::RefCell<&'a mut Context<'cx>>,
+        it: &'a clean::Item,
+        s: &'a clean::Union,
+    }
 
-    document(w, cx, it, None, HeadingOffset::H2);
+    impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
+        fn render_assoc_items<'b>(
+            &'b self,
+        ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
+            display_fn(move |f| {
+                let def_id = self.it.item_id.expect_def_id();
+                let mut cx = self.cx.borrow_mut();
+                let v = render_assoc_items(*cx, self.it, def_id, AssocItemRender::All);
+                write!(f, "{v}")
+            })
+        }
+        fn document_type_layout<'b>(
+            &'b self,
+        ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
+            display_fn(move |f| {
+                let def_id = self.it.item_id.expect_def_id();
+                let cx = self.cx.borrow_mut();
+                let v = document_type_layout(*cx, def_id);
+                write!(f, "{v}")
+            })
+        }
+        fn render_union<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
+            display_fn(move |f| {
+                let cx = self.cx.borrow_mut();
+                let v = render_union(self.it, Some(&self.s.generics), &self.s.fields, *cx);
+                write!(f, "{v}")
+            })
+        }
+        fn render_attributes_in_pre<'b>(
+            &'b self,
+        ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
+            display_fn(move |f| {
+                let v = render_attributes_in_pre(self.it, "");
+                write!(f, "{v}")
+            })
+        }
+        fn document<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
+            display_fn(move |f| {
+                let mut cx = self.cx.borrow_mut();
+                let v = document(*cx, self.it, None, HeadingOffset::H2);
+                write!(f, "{v}")
+            })
+        }
+        fn document_field<'b>(
+            &'b self,
+            field: &'a clean::Item,
+        ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
+            display_fn(move |f| {
+                let mut cx = self.cx.borrow_mut();
+                let v = document(*cx, field, Some(self.it), HeadingOffset::H3);
+                write!(f, "{v}")
+            })
+        }
+        fn stability_field(&self, field: &clean::Item) -> Option<String> {
+            let cx = self.cx.borrow();
+            field.stability_class(cx.tcx())
+        }
+        fn print_ty<'b>(
+            &'b self,
+            ty: &'a clean::Type,
+        ) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
+            display_fn(move |f| {
+                let cx = self.cx.borrow();
+                let v = ty.print(*cx);
+                write!(f, "{v}")
+            })
+        }
 
-    let mut fields = s
-        .fields
-        .iter()
-        .filter_map(|f| match *f.kind {
-            clean::StructFieldItem(ref ty) => Some((f, ty)),
-            _ => None,
-        })
-        .peekable();
-    if fields.peek().is_some() {
-        write!(
-            w,
-            "<h2 id=\"fields\" class=\"fields small-section-header\">\
-                Fields<a href=\"#fields\" class=\"anchor\">§</a>\
-            </h2>"
-        );
-        for (field, ty) in fields {
-            let name = field.name.expect("union field name");
-            let id = format!("{}.{}", ItemType::StructField, name);
-            write!(
-                w,
-                "<span id=\"{id}\" class=\"{shortty} small-section-header\">\
-                     <a href=\"#{id}\" class=\"anchor field\">§</a>\
-                     <code>{name}: {ty}</code>\
-                 </span>",
-                shortty = ItemType::StructField,
-                ty = ty.print(cx),
-            );
-            if let Some(stability_class) = field.stability_class(cx.tcx()) {
-                write!(w, "<span class=\"stab {stability_class}\"></span>");
-            }
-            document(w, cx, field, Some(it), HeadingOffset::H3);
+        fn fields_iter(
+            &self,
+        ) -> std::iter::Peekable<impl Iterator<Item = (&'a clean::Item, &'a clean::Type)>> {
+            self.s
+                .fields
+                .iter()
+                .filter_map(|f| match *f.kind {
+                    clean::StructFieldItem(ref ty) => Some((f, ty)),
+                    _ => None,
+                })
+                .peekable()
         }
     }
-    let def_id = it.item_id.expect_def_id();
-    render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
-    document_type_layout(w, cx, def_id);
+
+    ItemUnion { cx: std::cell::RefCell::new(cx), it, s }.render_into(w).unwrap();
 }
 
-fn print_tuple_struct_fields(w: &mut Buffer, cx: &Context<'_>, s: &[clean::Item]) {
-    for (i, ty) in s.iter().enumerate() {
-        if i > 0 {
-            w.write_str(", ");
-        }
-        match *ty.kind {
-            clean::StrippedItem(box clean::StructFieldItem(_)) => w.write_str("_"),
-            clean::StructFieldItem(ref ty) => write!(w, "{}", ty.print(cx)),
-            _ => unreachable!(),
+fn print_tuple_struct_fields<'a, 'cx: 'a>(
+    cx: &'a Context<'cx>,
+    s: &'a [clean::Item],
+) -> impl fmt::Display + 'a + Captures<'cx> {
+    display_fn(|f| {
+        for (i, ty) in s.iter().enumerate() {
+            if i > 0 {
+                f.write_str(", ")?;
+            }
+            match *ty.kind {
+                clean::StrippedItem(box clean::StructFieldItem(_)) => f.write_str("_")?,
+                clean::StructFieldItem(ref ty) => write!(f, "{}", ty.print(cx))?,
+                _ => unreachable!(),
+            }
         }
-    }
+        Ok(())
+    })
 }
 
 fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::Enum) {
     let tcx = cx.tcx();
     let count_variants = e.variants().count();
-    wrap_item(w, |w| {
-        render_attributes_in_pre(w, it, "");
+    wrap_item(w, |mut w| {
         write!(
             w,
-            "{}enum {}{}",
+            "{attrs}{}enum {}{}",
             visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
             it.name.unwrap(),
             e.generics.print(cx),
+            attrs = render_attributes_in_pre(it, ""),
         );
         if !print_where_clause_and_check(w, &e.generics, cx) {
             // If there wasn't a `where` clause, we add a whitespace.
@@ -1211,7 +1266,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
             w.write_str("{\n");
             let toggle = should_hide_fields(count_variants);
             if toggle {
-                toggle_open(w, format_args!("{} variants", count_variants));
+                toggle_open(&mut w, format_args!("{} variants", count_variants));
             }
             for v in e.variants() {
                 w.write_str("    ");
@@ -1221,9 +1276,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
                     clean::VariantItem(ref var) => match var.kind {
                         clean::VariantKind::CLike => write!(w, "{}", name),
                         clean::VariantKind::Tuple(ref s) => {
-                            write!(w, "{}(", name);
-                            print_tuple_struct_fields(w, cx, s);
-                            w.write_str(")");
+                            write!(w, "{name}({})", print_tuple_struct_fields(cx, s),);
                         }
                         clean::VariantKind::Struct(ref s) => {
                             render_struct(w, v, None, None, &s.fields, "    ", false, cx);
@@ -1238,24 +1291,25 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
                 w.write_str("    // some variants omitted\n");
             }
             if toggle {
-                toggle_close(w);
+                toggle_close(&mut w);
             }
             w.write_str("}");
         }
     });
 
-    document(w, cx, it, None, HeadingOffset::H2);
+    write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
 
     if count_variants != 0 {
         write!(
             w,
             "<h2 id=\"variants\" class=\"variants small-section-header\">\
                 Variants{}<a href=\"#variants\" class=\"anchor\">§</a>\
-            </h2>",
-            document_non_exhaustive_header(it)
+            </h2>\
+            {}\
+            <div class=\"variants\">",
+            document_non_exhaustive_header(it),
+            document_non_exhaustive(it)
         );
-        document_non_exhaustive(w, it);
-        write!(w, "<div class=\"variants\">");
         for variant in e.variants() {
             let id = cx.derive_id(format!("{}.{}", ItemType::Variant, variant.name.unwrap()));
             write!(
@@ -1276,9 +1330,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
             let clean::VariantItem(variant_data) = &*variant.kind else { unreachable!() };
 
             if let clean::VariantKind::Tuple(ref s) = variant_data.kind {
-                w.write_str("(");
-                print_tuple_struct_fields(w, cx, s);
-                w.write_str(")");
+                write!(w, "({})", print_tuple_struct_fields(cx, s),);
             }
             w.write_str("</h3></section>");
 
@@ -1302,9 +1354,10 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
                 write!(
                     w,
                     "<div class=\"sub-variant\" id=\"{variant_id}\">\
-                        <h4>{heading}</h4>",
+                        <h4>{heading}</h4>\
+                        {}",
+                    document_non_exhaustive(variant)
                 );
-                document_non_exhaustive(w, variant);
                 for field in fields {
                     match *field.kind {
                         clean::StrippedItem(box clean::StructFieldItem(_)) => {}
@@ -1322,10 +1375,13 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
                                      <code>{f}: {t}</code>\
                                  </span>",
                                 f = field.name.unwrap(),
-                                t = ty.print(cx)
+                                t = ty.print(cx),
+                            );
+                            write!(
+                                w,
+                                "{}</div>",
+                                document(cx, field, Some(variant), HeadingOffset::H5)
                             );
-                            document(w, cx, field, Some(variant), HeadingOffset::H5);
-                            write!(w, "</div>");
                         }
                         _ => unreachable!(),
                     }
@@ -1333,18 +1389,18 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
                 w.write_str("</div>");
             }
 
-            document(w, cx, variant, Some(it), HeadingOffset::H4);
+            write!(w, "{}", document(cx, variant, Some(it), HeadingOffset::H4));
         }
         write!(w, "</div>");
     }
     let def_id = it.item_id.expect_def_id();
-    render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
-    document_type_layout(w, cx, def_id);
+    write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All));
+    write!(w, "{}", document_type_layout(cx, def_id));
 }
 
 fn item_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Macro) {
     highlight::render_item_decl_with_highlighting(&t.source, w);
-    document(w, cx, it, None, HeadingOffset::H2)
+    write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
 }
 
 fn item_proc_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, m: &clean::ProcMacro) {
@@ -1370,14 +1426,14 @@ fn item_proc_macro(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, m: &c
             }
         }
     });
-    document(w, cx, it, None, HeadingOffset::H2)
+    write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
 }
 
 fn item_primitive(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
     let def_id = it.item_id.expect_def_id();
-    document(w, cx, it, None, HeadingOffset::H2);
+    write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
     if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) {
-        render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
+        write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All));
     } else {
         // We handle the "reference" primitive type on its own because we only want to list
         // implementations on generic types.
@@ -1433,7 +1489,7 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle
         }
     });
 
-    document(w, cx, it, None, HeadingOffset::H2)
+    write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
 }
 
 fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Struct) {
@@ -1442,7 +1498,7 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
         render_struct(w, it, Some(&s.generics), s.ctor_kind, &s.fields, "", true, cx);
     });
 
-    document(w, cx, it, None, HeadingOffset::H2);
+    write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
 
     let mut fields = s
         .fields
@@ -1458,11 +1514,12 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
                 w,
                 "<h2 id=\"fields\" class=\"fields small-section-header\">\
                      {}{}<a href=\"#fields\" class=\"anchor\">§</a>\
-                 </h2>",
+                 </h2>\
+                 {}",
                 if s.ctor_kind.is_none() { "Fields" } else { "Tuple Fields" },
-                document_non_exhaustive_header(it)
+                document_non_exhaustive_header(it),
+                document_non_exhaustive(it)
             );
-            document_non_exhaustive(w, it);
             for (index, (field, ty)) in fields.enumerate() {
                 let field_name =
                     field.name.map_or_else(|| index.to_string(), |sym| sym.as_str().to_string());
@@ -1476,13 +1533,13 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
                     item_type = ItemType::StructField,
                     ty = ty.print(cx)
                 );
-                document(w, cx, field, Some(it), HeadingOffset::H3);
+                write!(w, "{}", document(cx, field, Some(it), HeadingOffset::H3));
             }
         }
     }
     let def_id = it.item_id.expect_def_id();
-    render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
-    document_type_layout(w, cx, def_id);
+    write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All));
+    write!(w, "{}", document_type_layout(cx, def_id));
 }
 
 fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean::Static) {
@@ -1497,7 +1554,7 @@ fn item_static(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
             typ = s.type_.print(cx)
         );
     });
-    document(w, cx, it, None, HeadingOffset::H2)
+    write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
 }
 
 fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
@@ -1512,13 +1569,13 @@ fn item_foreign_type(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
         );
     });
 
-    document(w, cx, it, None, HeadingOffset::H2);
+    write!(w, "{}", document(cx, it, None, HeadingOffset::H2));
 
-    render_assoc_items(w, cx, it, it.item_id.expect_def_id(), AssocItemRender::All)
+    write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All))
 }
 
 fn item_keyword(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) {
-    document(w, cx, it, None, HeadingOffset::H2)
+    write!(w, "{}", document(cx, it, None, HeadingOffset::H2))
 }
 
 /// Compare two strings treating multi-digit numbers as single units (i.e. natural sort order).
@@ -1655,64 +1712,69 @@ fn render_implementor(
     );
 }
 
-fn render_union(
-    w: &mut Buffer,
-    it: &clean::Item,
-    g: Option<&clean::Generics>,
-    fields: &[clean::Item],
-    cx: &Context<'_>,
-) {
-    let tcx = cx.tcx();
-    write!(
-        w,
-        "{}union {}",
-        visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
-        it.name.unwrap(),
-    );
-
-    let where_displayed = g
-        .map(|g| {
-            write!(w, "{}", g.print(cx));
-            print_where_clause_and_check(w, g, cx)
-        })
-        .unwrap_or(false);
+fn render_union<'a, 'cx: 'a>(
+    it: &'a clean::Item,
+    g: Option<&'a clean::Generics>,
+    fields: &'a [clean::Item],
+    cx: &'a Context<'cx>,
+) -> impl fmt::Display + 'a + Captures<'cx> {
+    display_fn(move |mut f| {
+        let tcx = cx.tcx();
+        write!(
+            f,
+            "{}union {}",
+            visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
+            it.name.unwrap(),
+        )?;
+
+        let where_displayed = g
+            .map(|g| {
+                let mut buf = Buffer::html();
+                write!(buf, "{}", g.print(cx));
+                let where_displayed = print_where_clause_and_check(&mut buf, g, cx);
+                write!(f, "{buf}", buf = buf.into_inner()).unwrap();
+                where_displayed
+            })
+            .unwrap_or(false);
 
-    // If there wasn't a `where` clause, we add a whitespace.
-    if !where_displayed {
-        w.write_str(" ");
-    }
+        // If there wasn't a `where` clause, we add a whitespace.
+        if !where_displayed {
+            f.write_str(" ")?;
+        }
 
-    write!(w, "{{\n");
-    let count_fields =
-        fields.iter().filter(|f| matches!(*f.kind, clean::StructFieldItem(..))).count();
-    let toggle = should_hide_fields(count_fields);
-    if toggle {
-        toggle_open(w, format_args!("{} fields", count_fields));
-    }
+        write!(f, "{{\n")?;
+        let count_fields =
+            fields.iter().filter(|field| matches!(*field.kind, clean::StructFieldItem(..))).count();
+        let toggle = should_hide_fields(count_fields);
+        if toggle {
+            toggle_open(&mut f, format_args!("{} fields", count_fields));
+        }
 
-    for field in fields {
-        if let clean::StructFieldItem(ref ty) = *field.kind {
-            write!(
-                w,
-                "    {}{}: {},\n",
-                visibility_print_with_space(field.visibility(tcx), field.item_id, cx),
-                field.name.unwrap(),
-                ty.print(cx)
-            );
+        for field in fields {
+            if let clean::StructFieldItem(ref ty) = *field.kind {
+                write!(
+                    f,
+                    "    {}{}: {},\n",
+                    visibility_print_with_space(field.visibility(tcx), field.item_id, cx),
+                    field.name.unwrap(),
+                    ty.print(cx)
+                )?;
+            }
         }
-    }
 
-    if it.has_stripped_entries().unwrap() {
-        write!(w, "    /* private fields */\n");
-    }
-    if toggle {
-        toggle_close(w);
-    }
-    w.write_str("}");
+        if it.has_stripped_entries().unwrap() {
+            write!(f, "    /* private fields */\n")?;
+        }
+        if toggle {
+            toggle_close(&mut f);
+        }
+        f.write_str("}").unwrap();
+        Ok(())
+    })
 }
 
 fn render_struct(
-    w: &mut Buffer,
+    mut w: &mut Buffer,
     it: &clean::Item,
     g: Option<&clean::Generics>,
     ty: Option<CtorKind>,
@@ -1747,7 +1809,7 @@ fn render_struct(
             let has_visible_fields = count_fields > 0;
             let toggle = should_hide_fields(count_fields);
             if toggle {
-                toggle_open(w, format_args!("{} fields", count_fields));
+                toggle_open(&mut w, format_args!("{} fields", count_fields));
             }
             for field in fields {
                 if let clean::StructFieldItem(ref ty) = *field.kind {
@@ -1771,7 +1833,7 @@ fn render_struct(
                 write!(w, " /* private fields */ ");
             }
             if toggle {
-                toggle_close(w);
+                toggle_close(&mut w);
             }
             w.write_str("}");
         }
@@ -1817,161 +1879,169 @@ fn document_non_exhaustive_header(item: &clean::Item) -> &str {
     if item.is_non_exhaustive() { " (Non-exhaustive)" } else { "" }
 }
 
-fn document_non_exhaustive(w: &mut Buffer, item: &clean::Item) {
-    if item.is_non_exhaustive() {
-        write!(
-            w,
-            "<details class=\"toggle non-exhaustive\">\
-                 <summary class=\"hideme\"><span>{}</span></summary>\
-                 <div class=\"docblock\">",
-            {
-                if item.is_struct() {
-                    "This struct is marked as non-exhaustive"
-                } else if item.is_enum() {
-                    "This enum is marked as non-exhaustive"
-                } else if item.is_variant() {
-                    "This variant is marked as non-exhaustive"
-                } else {
-                    "This type is marked as non-exhaustive"
+fn document_non_exhaustive<'a>(item: &'a clean::Item) -> impl fmt::Display + 'a {
+    display_fn(|f| {
+        if item.is_non_exhaustive() {
+            write!(
+                f,
+                "<details class=\"toggle non-exhaustive\">\
+                    <summary class=\"hideme\"><span>{}</span></summary>\
+                    <div class=\"docblock\">",
+                {
+                    if item.is_struct() {
+                        "This struct is marked as non-exhaustive"
+                    } else if item.is_enum() {
+                        "This enum is marked as non-exhaustive"
+                    } else if item.is_variant() {
+                        "This variant is marked as non-exhaustive"
+                    } else {
+                        "This type is marked as non-exhaustive"
+                    }
                 }
+            )?;
+
+            if item.is_struct() {
+                f.write_str(
+                    "Non-exhaustive structs could have additional fields added in future. \
+                    Therefore, non-exhaustive structs cannot be constructed in external crates \
+                    using the traditional <code>Struct { .. }</code> syntax; cannot be \
+                    matched against without a wildcard <code>..</code>; and \
+                    struct update syntax will not work.",
+                )?;
+            } else if item.is_enum() {
+                f.write_str(
+                    "Non-exhaustive enums could have additional variants added in future. \
+                    Therefore, when matching against variants of non-exhaustive enums, an \
+                    extra wildcard arm must be added to account for any future variants.",
+                )?;
+            } else if item.is_variant() {
+                f.write_str(
+                    "Non-exhaustive enum variants could have additional fields added in future. \
+                    Therefore, non-exhaustive enum variants cannot be constructed in external \
+                    crates and cannot be matched against.",
+                )?;
+            } else {
+                f.write_str(
+                    "This type will require a wildcard arm in any match statements or constructors.",
+                )?;
             }
-        );
 
-        if item.is_struct() {
-            w.write_str(
-                "Non-exhaustive structs could have additional fields added in future. \
-                 Therefore, non-exhaustive structs cannot be constructed in external crates \
-                 using the traditional <code>Struct { .. }</code> syntax; cannot be \
-                 matched against without a wildcard <code>..</code>; and \
-                 struct update syntax will not work.",
-            );
-        } else if item.is_enum() {
-            w.write_str(
-                "Non-exhaustive enums could have additional variants added in future. \
-                 Therefore, when matching against variants of non-exhaustive enums, an \
-                 extra wildcard arm must be added to account for any future variants.",
-            );
-        } else if item.is_variant() {
-            w.write_str(
-                "Non-exhaustive enum variants could have additional fields added in future. \
-                 Therefore, non-exhaustive enum variants cannot be constructed in external \
-                 crates and cannot be matched against.",
-            );
-        } else {
-            w.write_str(
-                "This type will require a wildcard arm in any match statements or constructors.",
-            );
+            f.write_str("</div></details>")?;
         }
-
-        w.write_str("</div></details>");
-    }
+        Ok(())
+    })
 }
 
-fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) {
-    fn write_size_of_layout(w: &mut Buffer, layout: &LayoutS, tag_size: u64) {
+fn document_type_layout<'a, 'cx: 'a>(
+    cx: &'a Context<'cx>,
+    ty_def_id: DefId,
+) -> impl fmt::Display + 'a + Captures<'cx> {
+    fn write_size_of_layout(mut w: impl fmt::Write, layout: &LayoutS, tag_size: u64) {
         if layout.abi.is_unsized() {
-            write!(w, "(unsized)");
+            write!(w, "(unsized)").unwrap();
         } else {
             let size = layout.size.bytes() - tag_size;
-            write!(w, "{size} byte{pl}", pl = if size == 1 { "" } else { "s" },);
+            write!(w, "{size} byte{pl}", pl = if size == 1 { "" } else { "s" }).unwrap();
             if layout.abi.is_uninhabited() {
                 write!(
                     w,
                     " (<a href=\"https://doc.rust-lang.org/stable/reference/glossary.html#uninhabited\">uninhabited</a>)"
-                );
+                ).unwrap();
             }
         }
     }
 
-    if !cx.shared.show_type_layout {
-        return;
-    }
-
-    writeln!(
-        w,
-        "<h2 id=\"layout\" class=\"small-section-header\"> \
-        Layout<a href=\"#layout\" class=\"anchor\">§</a></h2>"
-    );
-    writeln!(w, "<div class=\"docblock\">");
-
-    let tcx = cx.tcx();
-    let param_env = tcx.param_env(ty_def_id);
-    let ty = tcx.type_of(ty_def_id).subst_identity();
-    match tcx.layout_of(param_env.and(ty)) {
-        Ok(ty_layout) => {
-            writeln!(
-                w,
-                "<div class=\"warning\"><p><strong>Note:</strong> Most layout information is \
-                 <strong>completely unstable</strong> and may even differ between compilations. \
-                 The only exception is types with certain <code>repr(...)</code> attributes. \
-                 Please see the Rust Reference’s \
-                 <a href=\"https://doc.rust-lang.org/reference/type-layout.html\">“Type Layout”</a> \
-                 chapter for details on type layout guarantees.</p></div>"
-            );
-            w.write_str("<p><strong>Size:</strong> ");
-            write_size_of_layout(w, &ty_layout.layout.0, 0);
-            writeln!(w, "</p>");
-            if let Variants::Multiple { variants, tag, tag_encoding, .. } =
-                &ty_layout.layout.variants()
-            {
-                if !variants.is_empty() {
-                    w.write_str(
-                        "<p><strong>Size for each variant:</strong></p>\
-                            <ul>",
-                    );
-
-                    let Adt(adt, _) = ty_layout.ty.kind() else {
-                        span_bug!(tcx.def_span(ty_def_id), "not an adt")
-                    };
+    display_fn(move |mut f| {
+        if !cx.shared.show_type_layout {
+            return Ok(());
+        }
 
-                    let tag_size = if let TagEncoding::Niche { .. } = tag_encoding {
-                        0
-                    } else if let Primitive::Int(i, _) = tag.primitive() {
-                        i.size().bytes()
-                    } else {
-                        span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int")
-                    };
+        writeln!(
+            f,
+            "<h2 id=\"layout\" class=\"small-section-header\"> \
+            Layout<a href=\"#layout\" class=\"anchor\">§</a></h2>"
+        )?;
+        writeln!(f, "<div class=\"docblock\">")?;
 
-                    for (index, layout) in variants.iter_enumerated() {
-                        let name = adt.variant(index).name;
-                        write!(w, "<li><code>{name}</code>: ");
-                        write_size_of_layout(w, layout, tag_size);
-                        writeln!(w, "</li>");
+        let tcx = cx.tcx();
+        let param_env = tcx.param_env(ty_def_id);
+        let ty = tcx.type_of(ty_def_id).subst_identity();
+        match tcx.layout_of(param_env.and(ty)) {
+            Ok(ty_layout) => {
+                writeln!(
+                    f,
+                    "<div class=\"warning\"><p><strong>Note:</strong> Most layout information is \
+                    <strong>completely unstable</strong> and may even differ between compilations. \
+                    The only exception is types with certain <code>repr(...)</code> attributes. \
+                    Please see the Rust Reference’s \
+                    <a href=\"https://doc.rust-lang.org/reference/type-layout.html\">“Type Layout”</a> \
+                    chapter for details on type layout guarantees.</p></div>"
+                )?;
+                f.write_str("<p><strong>Size:</strong> ")?;
+                write_size_of_layout(&mut f, &ty_layout.layout.0, 0);
+                writeln!(f, "</p>")?;
+                if let Variants::Multiple { variants, tag, tag_encoding, .. } =
+                    &ty_layout.layout.variants()
+                {
+                    if !variants.is_empty() {
+                        f.write_str(
+                            "<p><strong>Size for each variant:</strong></p>\
+                                <ul>",
+                        )?;
+
+                        let Adt(adt, _) = ty_layout.ty.kind() else {
+                            span_bug!(tcx.def_span(ty_def_id), "not an adt")
+                        };
+
+                        let tag_size = if let TagEncoding::Niche { .. } = tag_encoding {
+                            0
+                        } else if let Primitive::Int(i, _) = tag.primitive() {
+                            i.size().bytes()
+                        } else {
+                            span_bug!(tcx.def_span(ty_def_id), "tag is neither niche nor int")
+                        };
+
+                        for (index, layout) in variants.iter_enumerated() {
+                            let name = adt.variant(index).name;
+                            write!(&mut f, "<li><code>{name}</code>: ")?;
+                            write_size_of_layout(&mut f, layout, tag_size);
+                            writeln!(&mut f, "</li>")?;
+                        }
+                        f.write_str("</ul>")?;
                     }
-                    w.write_str("</ul>");
                 }
             }
+            // This kind of layout error can occur with valid code, e.g. if you try to
+            // get the layout of a generic type such as `Vec<T>`.
+            Err(LayoutError::Unknown(_)) => {
+                writeln!(
+                    f,
+                    "<p><strong>Note:</strong> Unable to compute type layout, \
+                    possibly due to this type having generic parameters. \
+                    Layout can only be computed for concrete, fully-instantiated types.</p>"
+                )?;
+            }
+            // This kind of error probably can't happen with valid code, but we don't
+            // want to panic and prevent the docs from building, so we just let the
+            // user know that we couldn't compute the layout.
+            Err(LayoutError::SizeOverflow(_)) => {
+                writeln!(
+                    f,
+                    "<p><strong>Note:</strong> Encountered an error during type layout; \
+                    the type was too big.</p>"
+                )?;
+            }
+            Err(LayoutError::NormalizationFailure(_, _)) => {
+                writeln!(
+                    f,
+                    "<p><strong>Note:</strong> Encountered an error during type layout; \
+                    the type failed to be normalized.</p>"
+                )?;
+            }
         }
-        // This kind of layout error can occur with valid code, e.g. if you try to
-        // get the layout of a generic type such as `Vec<T>`.
-        Err(LayoutError::Unknown(_)) => {
-            writeln!(
-                w,
-                "<p><strong>Note:</strong> Unable to compute type layout, \
-                 possibly due to this type having generic parameters. \
-                 Layout can only be computed for concrete, fully-instantiated types.</p>"
-            );
-        }
-        // This kind of error probably can't happen with valid code, but we don't
-        // want to panic and prevent the docs from building, so we just let the
-        // user know that we couldn't compute the layout.
-        Err(LayoutError::SizeOverflow(_)) => {
-            writeln!(
-                w,
-                "<p><strong>Note:</strong> Encountered an error during type layout; \
-                 the type was too big.</p>"
-            );
-        }
-        Err(LayoutError::NormalizationFailure(_, _)) => {
-            writeln!(
-                w,
-                "<p><strong>Note:</strong> Encountered an error during type layout; \
-                the type failed to be normalized.</p>"
-            )
-        }
-    }
 
-    writeln!(w, "</div>");
+        writeln!(f, "</div>")
+    })
 }
 
 fn pluralize(count: usize) -> &'static str {
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index 1d298f52f75..c8397967c87 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -2,7 +2,6 @@ use crate::clean;
 use crate::docfs::PathError;
 use crate::error::Error;
 use crate::html::format;
-use crate::html::format::Buffer;
 use crate::html::highlight;
 use crate::html::layout;
 use crate::html::render::Context;
@@ -17,6 +16,7 @@ use rustc_span::source_map::FileName;
 
 use std::cell::RefCell;
 use std::ffi::OsStr;
+use std::fmt;
 use std::fs;
 use std::ops::RangeInclusive;
 use std::path::{Component, Path, PathBuf};
@@ -294,7 +294,7 @@ pub(crate) enum SourceContext {
 /// Wrapper struct to render the source code of a file. This will do things like
 /// adding line numbers to the left-hand side.
 pub(crate) fn print_src(
-    buf: &mut Buffer,
+    mut writer: impl fmt::Write,
     s: &str,
     file_span: rustc_span::Span,
     context: &Context<'_>,
@@ -329,5 +329,5 @@ pub(crate) fn print_src(
         );
         Ok(())
     });
-    Source { embedded, needs_expansion, lines, code_html: code }.render_into(buf).unwrap();
+    Source { embedded, needs_expansion, lines, code_html: code }.render_into(&mut writer).unwrap();
 }
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 45c0360a49e..56ee4c1510e 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -332,13 +332,7 @@ function preLoadCss(cssUrl) {
     };
 
     function getPageId() {
-        if (window.location.hash) {
-            const tmp = window.location.hash.replace(/^#/, "");
-            if (tmp.length > 0) {
-                return tmp;
-            }
-        }
-        return null;
+        return window.location.hash.replace(/^#/, "");
     }
 
     const toggleAllDocsId = "toggle-all-docs";
@@ -707,7 +701,7 @@ function preLoadCss(cssUrl) {
         });
 
         const pageId = getPageId();
-        if (pageId !== null) {
+        if (pageId !== "") {
             expandSection(pageId);
         }
     }());
diff --git a/src/librustdoc/html/static/js/settings.js b/src/librustdoc/html/static/js/settings.js
index 1cd552e7f25..ebbe6c1ca9a 100644
--- a/src/librustdoc/html/static/js/settings.js
+++ b/src/librustdoc/html/static/js/settings.js
@@ -86,12 +86,8 @@
             if (settingId === "theme") {
                 const useSystem = getSettingValue("use-system-theme");
                 if (useSystem === "true" || settingValue === null) {
-                    if (useSystem !== "false") {
-                        settingValue = "system preference";
-                    } else {
-                        // This is the default theme.
-                        settingValue = "light";
-                    }
+                    // "light" is the default theme
+                    settingValue = useSystem === "false" ? "light" : "system preference";
                 }
             }
             if (settingValue !== null && settingValue !== "null") {
diff --git a/src/librustdoc/html/static/js/storage.js b/src/librustdoc/html/static/js/storage.js
index 8d82b5b78ed..93979a94418 100644
--- a/src/librustdoc/html/static/js/storage.js
+++ b/src/librustdoc/html/static/js/storage.js
@@ -53,10 +53,9 @@ function removeClass(elem, className) {
  * @param {boolean}     [reversed] - Whether to iterate in reverse
  */
 function onEach(arr, func, reversed) {
-    if (arr && arr.length > 0 && func) {
+    if (arr && arr.length > 0) {
         if (reversed) {
-            const length = arr.length;
-            for (let i = length - 1; i >= 0; --i) {
+            for (let i = arr.length - 1; i >= 0; --i) {
                 if (func(arr[i])) {
                     return true;
                 }
@@ -150,26 +149,19 @@ const updateTheme = (function() {
      * … dictates that it should be.
      */
     function updateTheme() {
-        const use = (theme, saveTheme) => {
-            switchTheme(theme, saveTheme);
-        };
-
         // maybe the user has disabled the setting in the meantime!
         if (getSettingValue("use-system-theme") !== "false") {
             const lightTheme = getSettingValue("preferred-light-theme") || "light";
             const darkTheme = getSettingValue("preferred-dark-theme") || "dark";
+            updateLocalStorage("use-system-theme", "true");
 
-            if (mql.matches) {
-                use(darkTheme, true);
-            } else {
-                // prefers a light theme, or has no preference
-                use(lightTheme, true);
-            }
+            // use light theme if user prefers it, or has no preference
+            switchTheme(mql.matches ? darkTheme : lightTheme, true);
             // note: we save the theme so that it doesn't suddenly change when
             // the user disables "use-system-theme" and reloads the page or
             // navigates to another page
         } else {
-            use(getSettingValue("theme"), false);
+            switchTheme(getSettingValue("theme"), false);
         }
     }
 
diff --git a/src/librustdoc/html/templates/item_union.html b/src/librustdoc/html/templates/item_union.html
new file mode 100644
index 00000000000..a01457971c1
--- /dev/null
+++ b/src/librustdoc/html/templates/item_union.html
@@ -0,0 +1,23 @@
+<pre class="rust item-decl"><code>
+    {{ self.render_attributes_in_pre() | safe }}
+    {{ self.render_union() | safe }}
+</code></pre>
+{{ self.document() | safe }}
+{% if self.fields_iter().peek().is_some() %}
+    <h2 id="fields" class="fields small-section-header">
+        Fields<a href="#fields" class="anchor">§</a>
+    </h2>
+    {% for (field, ty) in self.fields_iter() %}
+        {% let name = field.name.expect("union field name") %}
+        <span id="structfield.{{ name }}" class="{{ ItemType::StructField }} small-section-header">
+            <a href="#structfield.{{ name }}" class="anchor field">§</a>
+            <code>{{ name }}: {{ self.print_ty(ty) | safe }}</code>
+        </span>
+        {% if let Some(stability_class) = self.stability_field(field) %}
+            <span class="stab {{ stability_class }}"></span>
+        {% endif %}
+        {{ self.document_field(field) | safe }}
+    {% endfor %}
+{% endif %}
+{{ self.render_assoc_items() | safe }}
+{{ self.document_type_layout() | safe }}
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index d66640ba0b7..354b6d71aa4 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -301,13 +301,13 @@ fn check_terminator<'tcx>(
         | TerminatorKind::Goto { .. }
         | TerminatorKind::Return
         | TerminatorKind::Resume
+        | TerminatorKind::Terminate
         | TerminatorKind::Unreachable => Ok(()),
 
         TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span, body),
 
         TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body),
 
-        TerminatorKind::Abort => Err((span, "abort is not stable in const fn".into())),
         TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => {
             Err((span, "const fn generators are unstable".into()))
         },
@@ -318,7 +318,7 @@ fn check_terminator<'tcx>(
             from_hir_call: _,
             destination: _,
             target: _,
-            cleanup: _,
+            unwind: _,
             fn_span: _,
         } => {
             let fn_ty = func.ty(body, tcx);
@@ -361,7 +361,7 @@ fn check_terminator<'tcx>(
             expected: _,
             msg: _,
             target: _,
-            cleanup: _,
+            unwind: _,
         } => check_operand(tcx, cond, span, body),
 
         TerminatorKind::InlineAsm { .. } => Err((span, "cannot use inline assembly in const fn".into())),
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 21a413002d0..8f6ae729491 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -951,7 +951,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         if this.machine.panic_on_unsupported {
             // message is slightly different here to make automated analysis easier
             let error_msg = format!("unsupported Miri functionality: {}", error_msg.as_ref());
-            this.start_panic(error_msg.as_ref(), StackPopUnwind::Skip)?;
+            this.start_panic(error_msg.as_ref(), mir::UnwindAction::Continue)?;
             Ok(())
         } else {
             throw_unsup_format!("{}", error_msg.as_ref());
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 01d0f01d319..fb4e59acd00 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -5,7 +5,6 @@
 #![feature(io_error_more)]
 #![feature(variant_count)]
 #![feature(yeet_expr)]
-#![feature(is_some_and)]
 #![feature(nonzero_ops)]
 #![feature(local_key_cell_methods)]
 #![feature(is_terminal)]
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index cc1964de332..477d8d33ebb 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -834,7 +834,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         args: &[OpTy<'tcx, Provenance>],
         dest: &PlaceTy<'tcx, Provenance>,
         ret: Option<mir::BasicBlock>,
-        unwind: StackPopUnwind,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
         ecx.find_mir_or_eval_fn(instance, abi, args, dest, ret, unwind)
     }
@@ -847,7 +847,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         args: &[OpTy<'tcx, Provenance>],
         dest: &PlaceTy<'tcx, Provenance>,
         ret: Option<mir::BasicBlock>,
-        _unwind: StackPopUnwind,
+        _unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         ecx.call_dlsym(fn_val, abi, args, dest, ret)
     }
@@ -859,7 +859,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         args: &[OpTy<'tcx, Provenance>],
         dest: &PlaceTy<'tcx, Provenance>,
         ret: Option<mir::BasicBlock>,
-        unwind: StackPopUnwind,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         ecx.call_intrinsic(instance, args, dest, ret, unwind)
     }
@@ -868,7 +868,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     fn assert_panic(
         ecx: &mut MiriInterpCx<'mir, 'tcx>,
         msg: &mir::AssertMessage<'tcx>,
-        unwind: Option<mir::BasicBlock>,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         ecx.assert_panic(msg, unwind)
     }
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 73439133af2..fcee381ff71 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -258,7 +258,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         args: &[OpTy<'tcx, Provenance>],
         dest: &PlaceTy<'tcx, Provenance>,
         ret: Option<mir::BasicBlock>,
-        unwind: StackPopUnwind,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
         let this = self.eval_context_mut();
         let link_name = this.item_link_name(def_id);
diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs
index 9ecbb18ef5a..ca2c1652dc1 100644
--- a/src/tools/miri/src/shims/intrinsics/mod.rs
+++ b/src/tools/miri/src/shims/intrinsics/mod.rs
@@ -26,7 +26,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         args: &[OpTy<'tcx, Provenance>],
         dest: &PlaceTy<'tcx, Provenance>,
         ret: Option<mir::BasicBlock>,
-        _unwind: StackPopUnwind,
+        _unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs
index dbc48876a4b..918efda3777 100644
--- a/src/tools/miri/src/shims/mod.rs
+++ b/src/tools/miri/src/shims/mod.rs
@@ -34,7 +34,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         args: &[OpTy<'tcx, Provenance>],
         dest: &PlaceTy<'tcx, Provenance>,
         ret: Option<mir::BasicBlock>,
-        unwind: StackPopUnwind,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
         let this = self.eval_context_mut();
         trace!("eval_fn_call: {:#?}, {:?}", instance, dest);
@@ -70,7 +70,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         align_op: &OpTy<'tcx, Provenance>,
         dest: &PlaceTy<'tcx, Provenance>,
         ret: Option<mir::BasicBlock>,
-        unwind: StackPopUnwind,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx, bool> {
         let this = self.eval_context_mut();
         let ret = ret.unwrap();
diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs
index acc97c4b8a0..2cca2f3f391 100644
--- a/src/tools/miri/src/shims/panic.rs
+++ b/src/tools/miri/src/shims/panic.rs
@@ -53,7 +53,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         abi: Abi,
         link_name: Symbol,
         args: &[OpTy<'tcx, Provenance>],
-        unwind: StackPopUnwind,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
@@ -106,7 +106,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             &[data.into()],
             None,
             // Directly return to caller.
-            StackPopCleanup::Goto { ret: Some(ret), unwind: StackPopUnwind::Skip },
+            StackPopCleanup::Goto { ret: Some(ret), unwind: mir::UnwindAction::Continue },
         )?;
 
         // We ourselves will return `0`, eventually (will be overwritten if we catch a panic).
@@ -157,7 +157,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 &[catch_unwind.data.into(), payload.into()],
                 None,
                 // Directly return to caller of `try`.
-                StackPopCleanup::Goto { ret: Some(catch_unwind.ret), unwind: StackPopUnwind::Skip },
+                StackPopCleanup::Goto { ret: Some(catch_unwind.ret), unwind: mir::UnwindAction::Continue },
             )?;
 
             // We pushed a new stack frame, the engine should not do any jumping now!
@@ -168,7 +168,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     }
 
     /// Start a panic in the interpreter with the given message as payload.
-    fn start_panic(&mut self, msg: &str, unwind: StackPopUnwind) -> InterpResult<'tcx> {
+    fn start_panic(&mut self, msg: &str, unwind: mir::UnwindAction) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
         // First arg: message.
@@ -189,7 +189,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     fn assert_panic(
         &mut self,
         msg: &mir::AssertMessage<'tcx>,
-        unwind: Option<mir::BasicBlock>,
+        unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
         use rustc_middle::mir::AssertKind::*;
         let this = self.eval_context_mut();
@@ -213,10 +213,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     None,
                     StackPopCleanup::Goto {
                         ret: None,
-                        unwind: match unwind {
-                            Some(cleanup) => StackPopUnwind::Cleanup(cleanup),
-                            None => StackPopUnwind::Skip,
-                        },
+                        unwind,
                     },
                 )?;
             }
@@ -240,10 +237,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     None,
                     StackPopCleanup::Goto {
                         ret: None,
-                        unwind: match unwind {
-                            Some(cleanup) => StackPopUnwind::Cleanup(cleanup),
-                            None => StackPopUnwind::Skip,
-                        },
+                        unwind,
                     },
                 )?;
             }
@@ -252,10 +246,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // Forward everything else to `panic` lang item.
                 this.start_panic(
                     msg.description(),
-                    match unwind {
-                        Some(cleanup) => StackPopUnwind::Cleanup(cleanup),
-                        None => StackPopUnwind::Skip,
-                    },
+                    unwind,
                 )?;
             }
         }
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr
index 484f703f9c1..e1631471ae2 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr
@@ -1,6 +1,6 @@
 thread 'main' panicked at 'explicit panic', $DIR/exported_symbol_bad_unwind2.rs:LL:CC
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-error: abnormal termination: the program aborted execution
+error: abnormal termination: panic in a function that cannot unwind
   --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
    |
 LL | / extern "C-unwind" fn nounwind() {
@@ -8,7 +8,7 @@ LL | |
 LL | |
 LL | |     panic!();
 LL | | }
-   | |_^ the program aborted execution
+   | |_^ panic in a function that cannot unwind
    |
    = note: inside `nounwind` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
 note: inside `main`
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr
index 484f703f9c1..e1631471ae2 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr
@@ -1,6 +1,6 @@
 thread 'main' panicked at 'explicit panic', $DIR/exported_symbol_bad_unwind2.rs:LL:CC
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-error: abnormal termination: the program aborted execution
+error: abnormal termination: panic in a function that cannot unwind
   --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
    |
 LL | / extern "C-unwind" fn nounwind() {
@@ -8,7 +8,7 @@ LL | |
 LL | |
 LL | |     panic!();
 LL | | }
-   | |_^ the program aborted execution
+   | |_^ panic in a function that cannot unwind
    |
    = note: inside `nounwind` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
 note: inside `main`
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs
index 554cbe09cf0..65ba3433c28 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs
@@ -4,8 +4,8 @@
 #[cfg_attr(any(definition, both), rustc_nounwind)]
 #[no_mangle]
 extern "C-unwind" fn nounwind() {
-    //~[definition]^ ERROR: abnormal termination: the program aborted execution
-    //~[both]^^ ERROR: abnormal termination: the program aborted execution
+    //~[definition]^ ERROR: abnormal termination: panic in a function that cannot unwind
+    //~[both]^^ ERROR: abnormal termination: panic in a function that cannot unwind
     panic!();
 }
 
diff --git a/src/tools/miri/tests/fail/terminate-terminator.rs b/src/tools/miri/tests/fail/terminate-terminator.rs
new file mode 100644
index 00000000000..f4931659fc8
--- /dev/null
+++ b/src/tools/miri/tests/fail/terminate-terminator.rs
@@ -0,0 +1,27 @@
+//@compile-flags: -Zmir-opt-level=3
+// Enable MIR inlining to ensure that `TerminatorKind::Terminate` is generated
+// instead of just `UnwindAction::Terminate`.
+
+#![feature(c_unwind)]
+
+struct Foo;
+
+impl Drop for Foo {
+    fn drop(&mut self) {}
+}
+
+#[inline(always)]
+fn has_cleanup() {
+    //~^ ERROR: panic in a function that cannot unwind
+    // FIXME(nbdd0121): The error should be reported at the call site.
+    let _f = Foo;
+    panic!();
+}
+
+extern "C" fn panic_abort() {
+    has_cleanup();
+}
+
+fn main() {
+    panic_abort();
+}
diff --git a/src/tools/miri/tests/fail/terminate-terminator.stderr b/src/tools/miri/tests/fail/terminate-terminator.stderr
new file mode 100644
index 00000000000..3befd83007b
--- /dev/null
+++ b/src/tools/miri/tests/fail/terminate-terminator.stderr
@@ -0,0 +1,27 @@
+thread 'main' panicked at 'explicit panic', $DIR/terminate-terminator.rs:LL:CC
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+error: abnormal termination: panic in a function that cannot unwind
+  --> $DIR/terminate-terminator.rs:LL:CC
+   |
+LL | / fn has_cleanup() {
+LL | |
+LL | |     // FIXME(nbdd0121): The error should be reported at the call site.
+LL | |     let _f = Foo;
+LL | |     panic!();
+LL | | }
+   | |_^ panic in a function that cannot unwind
+...
+LL |       has_cleanup();
+   |       ------------- in this inlined function call
+   |
+   = note: inside `panic_abort` at $DIR/terminate-terminator.rs:LL:CC
+note: inside `main`
+  --> $DIR/terminate-terminator.rs:LL:CC
+   |
+LL |     panic_abort();
+   |     ^^^^^^^^^^^^^
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/abort-terminator.rs b/src/tools/miri/tests/fail/unwind-action-terminate.rs
index c954443a276..876b9a9ab0a 100644
--- a/src/tools/miri/tests/fail/abort-terminator.rs
+++ b/src/tools/miri/tests/fail/unwind-action-terminate.rs
@@ -1,7 +1,7 @@
 #![feature(c_unwind)]
 
 extern "C" fn panic_abort() {
-    //~^ ERROR: the program aborted
+    //~^ ERROR: panic in a function that cannot unwind
     panic!()
 }
 
diff --git a/src/tools/miri/tests/fail/abort-terminator.stderr b/src/tools/miri/tests/fail/unwind-action-terminate.stderr
index 2d3275f6b19..52a1879cb5f 100644
--- a/src/tools/miri/tests/fail/abort-terminator.stderr
+++ b/src/tools/miri/tests/fail/unwind-action-terminate.stderr
@@ -1,17 +1,17 @@
-thread 'main' panicked at 'explicit panic', $DIR/abort-terminator.rs:LL:CC
+thread 'main' panicked at 'explicit panic', $DIR/unwind-action-terminate.rs:LL:CC
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-error: abnormal termination: the program aborted execution
-  --> $DIR/abort-terminator.rs:LL:CC
+error: abnormal termination: panic in a function that cannot unwind
+  --> $DIR/unwind-action-terminate.rs:LL:CC
    |
 LL | / extern "C" fn panic_abort() {
 LL | |
 LL | |     panic!()
 LL | | }
-   | |_^ the program aborted execution
+   | |_^ panic in a function that cannot unwind
    |
-   = note: inside `panic_abort` at $DIR/abort-terminator.rs:LL:CC
+   = note: inside `panic_abort` at $DIR/unwind-action-terminate.rs:LL:CC
 note: inside `main`
-  --> $DIR/abort-terminator.rs:LL:CC
+  --> $DIR/unwind-action-terminate.rs:LL:CC
    |
 LL |     panic_abort();
    |     ^^^^^^^^^^^^^
diff --git a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir
index af5178d4079..4be382fac8c 100644
--- a/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir
+++ b/tests/mir-opt/array_index_is_temporary.main.SimplifyCfg-elaborate-drops.after.mir
@@ -38,7 +38,7 @@ fn main() -> () {
         _6 = _3;                         // scope 4 at $DIR/array_index_is_temporary.rs:+4:25: +4:26
         _5 = foo(move _6) -> bb1;        // scope 4 at $DIR/array_index_is_temporary.rs:+4:21: +4:27
                                          // mir::Constant
-                                         // + span: $DIR/array_index_is_temporary.rs:16:21: 16:24
+                                         // + span: $DIR/array_index_is_temporary.rs:17:21: 17:24
                                          // + literal: Const { ty: unsafe fn(*mut usize) -> u32 {foo}, val: Value(<ZST>) }
     }
 
diff --git a/tests/mir-opt/array_index_is_temporary.rs b/tests/mir-opt/array_index_is_temporary.rs
index e7bde81d4ca..702b9c70e59 100644
--- a/tests/mir-opt/array_index_is_temporary.rs
+++ b/tests/mir-opt/array_index_is_temporary.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Retagging (from Stacked Borrows) relies on the array index being a fresh
 // temporary, so that side-effects cannot change it.
 // Test that this is indeed the case.
diff --git a/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir b/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir
index 2487ef5c215..f6954ab3526 100644
--- a/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir
+++ b/tests/mir-opt/asm_unwind_panic_abort.main.AbortUnwindingCalls.after.mir
@@ -9,7 +9,7 @@ fn main() -> () {
     bb0: {
         StorageLive(_1);                 // scope 1 at $DIR/asm_unwind_panic_abort.rs:+2:9: +2:49
         _1 = const ();                   // scope 1 at $DIR/asm_unwind_panic_abort.rs:+2:9: +2:49
-        asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind: bb2]; // scope 1 at $DIR/asm_unwind_panic_abort.rs:+2:9: +2:49
+        asm!("", options(MAY_UNWIND)) -> [return: bb1, unwind terminate]; // scope 1 at $DIR/asm_unwind_panic_abort.rs:+2:9: +2:49
     }
 
     bb1: {
@@ -17,8 +17,4 @@ fn main() -> () {
         _0 = const ();                   // scope 1 at $DIR/asm_unwind_panic_abort.rs:+1:5: +3:6
         return;                          // scope 0 at $DIR/asm_unwind_panic_abort.rs:+4:2: +4:2
     }
-
-    bb2 (cleanup): {
-        abort;                           // scope 0 at $DIR/asm_unwind_panic_abort.rs:+0:1: +4:2
-    }
 }
diff --git a/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff b/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff
index 61a934685cd..d663c343515 100644
--- a/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff
+++ b/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff
@@ -47,7 +47,7 @@
   
       bb2 (cleanup): {
           _5 = move _6;                    // scope 4 at $DIR/basic_assignment.rs:+13:5: +13:11
-          drop(_6) -> bb6;                 // scope 4 at $DIR/basic_assignment.rs:+13:19: +13:20
+          drop(_6) -> [return: bb6, unwind terminate]; // scope 4 at $DIR/basic_assignment.rs:+13:19: +13:20
       }
   
       bb3: {
@@ -70,16 +70,20 @@
       }
   
       bb6 (cleanup): {
-          drop(_5) -> bb7;                 // scope 3 at $DIR/basic_assignment.rs:+14:1: +14:2
+          drop(_5) -> [return: bb7, unwind terminate]; // scope 3 at $DIR/basic_assignment.rs:+14:1: +14:2
       }
   
       bb7 (cleanup): {
--         drop(_4) -> bb8;                 // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2
+-         drop(_4) -> [return: bb8, unwind terminate]; // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2
 +         goto -> bb8;                     // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2
       }
   
       bb8 (cleanup): {
           resume;                          // scope 0 at $DIR/basic_assignment.rs:+0:1: +14:2
++     }
++ 
++     bb9 (cleanup): {
++         unreachable;                     // scope 0 at $DIR/basic_assignment.rs:+0:1: +14:2
       }
   }
   
diff --git a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir
index 6d1c7bd18dc..d63497e3a98 100644
--- a/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/basic_assignment.main.SimplifyCfg-initial.after.mir
@@ -51,7 +51,7 @@ fn main() -> () {
 
     bb2 (cleanup): {
         _5 = move _6;                    // scope 4 at $DIR/basic_assignment.rs:+13:5: +13:11
-        drop(_6) -> bb6;                 // scope 4 at $DIR/basic_assignment.rs:+13:19: +13:20
+        drop(_6) -> [return: bb6, unwind terminate]; // scope 4 at $DIR/basic_assignment.rs:+13:19: +13:20
     }
 
     bb3: {
@@ -73,11 +73,11 @@ fn main() -> () {
     }
 
     bb6 (cleanup): {
-        drop(_5) -> bb7;                 // scope 3 at $DIR/basic_assignment.rs:+14:1: +14:2
+        drop(_5) -> [return: bb7, unwind terminate]; // scope 3 at $DIR/basic_assignment.rs:+14:1: +14:2
     }
 
     bb7 (cleanup): {
-        drop(_4) -> bb8;                 // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2
+        drop(_4) -> [return: bb8, unwind terminate]; // scope 2 at $DIR/basic_assignment.rs:+14:1: +14:2
     }
 
     bb8 (cleanup): {
diff --git a/tests/mir-opt/box_expr.main.ElaborateDrops.before.mir b/tests/mir-opt/box_expr.main.ElaborateDrops.before.mir
index 1bbf8f37f29..bac5b21dfad 100644
--- a/tests/mir-opt/box_expr.main.ElaborateDrops.before.mir
+++ b/tests/mir-opt/box_expr.main.ElaborateDrops.before.mir
@@ -63,15 +63,15 @@ fn main() -> () {
     }
 
     bb6 (cleanup): {
-        drop(_7) -> bb7;                 // scope 1 at $DIR/box_expr.rs:+3:11: +3:12
+        drop(_7) -> [return: bb7, unwind terminate]; // scope 1 at $DIR/box_expr.rs:+3:11: +3:12
     }
 
     bb7 (cleanup): {
-        drop(_1) -> bb9;                 // scope 0 at $DIR/box_expr.rs:+4:1: +4:2
+        drop(_1) -> [return: bb9, unwind terminate]; // scope 0 at $DIR/box_expr.rs:+4:1: +4:2
     }
 
     bb8 (cleanup): {
-        drop(_5) -> bb9;                 // scope 0 at $DIR/box_expr.rs:+2:22: +2:23
+        drop(_5) -> [return: bb9, unwind terminate]; // scope 0 at $DIR/box_expr.rs:+2:22: +2:23
     }
 
     bb9 (cleanup): {
diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir
index fd6485de863..7cce3415fa1 100644
--- a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir
+++ b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir
@@ -98,14 +98,14 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>,
         StorageLive(_3);                 // scope 0 at $DIR/async_await.rs:+1:5: +1:14
         StorageLive(_4);                 // scope 0 at $DIR/async_await.rs:+1:8: +1:14
         StorageLive(_5);                 // scope 0 at $DIR/async_await.rs:+1:5: +1:8
-        _5 = a() -> bb2;                 // scope 0 at $DIR/async_await.rs:+1:5: +1:8
+        _5 = a() -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/async_await.rs:+1:5: +1:8
                                          // mir::Constant
                                          // + span: $DIR/async_await.rs:15:5: 15:6
                                          // + literal: Const { ty: fn() -> impl Future<Output = ()> {a}, val: Value(<ZST>) }
     }
 
     bb2: {
-        _4 = <impl Future<Output = ()> as IntoFuture>::into_future(move _5) -> bb3; // scope 0 at $DIR/async_await.rs:+1:8: +1:14
+        _4 = <impl Future<Output = ()> as IntoFuture>::into_future(move _5) -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/async_await.rs:+1:8: +1:14
                                          // mir::Constant
                                          // + span: $DIR/async_await.rs:15:8: 15:14
                                          // + literal: Const { ty: fn(impl Future<Output = ()>) -> <impl Future<Output = ()> as IntoFuture>::IntoFuture {<impl Future<Output = ()> as IntoFuture>::into_future}, val: Value(<ZST>) }
@@ -126,7 +126,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>,
         StorageLive(_12);                // scope 2 at $DIR/async_await.rs:+1:8: +1:14
         _12 = &mut (((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2])) as variant#3).0: impl std::future::Future<Output = ()>); // scope 2 at $DIR/async_await.rs:+1:8: +1:14
         _11 = &mut (*_12);               // scope 2 at $DIR/async_await.rs:+1:8: +1:14
-        _10 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _11) -> bb5; // scope 2 at $DIR/async_await.rs:+1:8: +1:14
+        _10 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _11) -> [return: bb5, unwind unreachable]; // scope 2 at $DIR/async_await.rs:+1:8: +1:14
                                          // mir::Constant
                                          // + span: $DIR/async_await.rs:15:8: 15:14
                                          // + literal: Const { ty: unsafe fn(&mut impl Future<Output = ()>) -> Pin<&mut impl Future<Output = ()>> {Pin::<&mut impl Future<Output = ()>>::new_unchecked}, val: Value(<ZST>) }
@@ -145,7 +145,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>,
     bb6: {
         _13 = &mut (*_14);               // scope 2 at $DIR/async_await.rs:+1:5: +1:14
         StorageDead(_15);                // scope 2 at $DIR/async_await.rs:+1:13: +1:14
-        _9 = <impl Future<Output = ()> as Future>::poll(move _10, move _13) -> bb7; // scope 2 at $DIR/async_await.rs:+1:8: +1:14
+        _9 = <impl Future<Output = ()> as Future>::poll(move _10, move _13) -> [return: bb7, unwind unreachable]; // scope 2 at $DIR/async_await.rs:+1:8: +1:14
                                          // mir::Constant
                                          // + span: $DIR/async_await.rs:15:8: 15:14
                                          // + literal: Const { ty: for<'a, 'b, 'c> fn(Pin<&'a mut impl Future<Output = ()>>, &'b mut Context<'c>) -> Poll<<impl Future<Output = ()> as Future>::Output> {<impl Future<Output = ()> as Future>::poll}, val: Value(<ZST>) }
@@ -206,14 +206,14 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>,
         StorageDead(_3);                 // scope 0 at $DIR/async_await.rs:+1:14: +1:15
         StorageLive(_21);                // scope 0 at $DIR/async_await.rs:+2:8: +2:14
         StorageLive(_22);                // scope 0 at $DIR/async_await.rs:+2:5: +2:8
-        _22 = a() -> bb14;               // scope 0 at $DIR/async_await.rs:+2:5: +2:8
+        _22 = a() -> [return: bb14, unwind unreachable]; // scope 0 at $DIR/async_await.rs:+2:5: +2:8
                                          // mir::Constant
                                          // + span: $DIR/async_await.rs:16:5: 16:6
                                          // + literal: Const { ty: fn() -> impl Future<Output = ()> {a}, val: Value(<ZST>) }
     }
 
     bb14: {
-        _21 = <impl Future<Output = ()> as IntoFuture>::into_future(move _22) -> bb15; // scope 0 at $DIR/async_await.rs:+2:8: +2:14
+        _21 = <impl Future<Output = ()> as IntoFuture>::into_future(move _22) -> [return: bb15, unwind unreachable]; // scope 0 at $DIR/async_await.rs:+2:8: +2:14
                                          // mir::Constant
                                          // + span: $DIR/async_await.rs:16:8: 16:14
                                          // + literal: Const { ty: fn(impl Future<Output = ()>) -> <impl Future<Output = ()> as IntoFuture>::IntoFuture {<impl Future<Output = ()> as IntoFuture>::into_future}, val: Value(<ZST>) }
@@ -234,7 +234,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>,
         StorageLive(_28);                // scope 5 at $DIR/async_await.rs:+2:8: +2:14
         _28 = &mut (((*(_1.0: &mut [async fn body@$DIR/async_await.rs:14:18: 17:2])) as variant#4).0: impl std::future::Future<Output = ()>); // scope 5 at $DIR/async_await.rs:+2:8: +2:14
         _27 = &mut (*_28);               // scope 5 at $DIR/async_await.rs:+2:8: +2:14
-        _26 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _27) -> bb17; // scope 5 at $DIR/async_await.rs:+2:8: +2:14
+        _26 = Pin::<&mut impl Future<Output = ()>>::new_unchecked(move _27) -> [return: bb17, unwind unreachable]; // scope 5 at $DIR/async_await.rs:+2:8: +2:14
                                          // mir::Constant
                                          // + span: $DIR/async_await.rs:16:8: 16:14
                                          // + literal: Const { ty: unsafe fn(&mut impl Future<Output = ()>) -> Pin<&mut impl Future<Output = ()>> {Pin::<&mut impl Future<Output = ()>>::new_unchecked}, val: Value(<ZST>) }
@@ -253,7 +253,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>,
     bb18: {
         _29 = &mut (*_30);               // scope 5 at $DIR/async_await.rs:+2:5: +2:14
         StorageDead(_31);                // scope 5 at $DIR/async_await.rs:+2:13: +2:14
-        _25 = <impl Future<Output = ()> as Future>::poll(move _26, move _29) -> bb19; // scope 5 at $DIR/async_await.rs:+2:8: +2:14
+        _25 = <impl Future<Output = ()> as Future>::poll(move _26, move _29) -> [return: bb19, unwind unreachable]; // scope 5 at $DIR/async_await.rs:+2:8: +2:14
                                          // mir::Constant
                                          // + span: $DIR/async_await.rs:16:8: 16:14
                                          // + literal: Const { ty: for<'a, 'b, 'c> fn(Pin<&'a mut impl Future<Output = ()>>, &'b mut Context<'c>) -> Poll<<impl Future<Output = ()> as Future>::Output> {<impl Future<Output = ()> as Future>::poll}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/building/enum_cast.droppy.built.after.mir b/tests/mir-opt/building/enum_cast.droppy.built.after.mir
index 5231c2eab95..1112177fbbf 100644
--- a/tests/mir-opt/building/enum_cast.droppy.built.after.mir
+++ b/tests/mir-opt/building/enum_cast.droppy.built.after.mir
@@ -63,7 +63,7 @@ fn droppy() -> () {
     }
 
     bb4 (cleanup): {
-        drop(_2) -> bb5;                 // scope 0 at $DIR/enum_cast.rs:+6:5: +6:6
+        drop(_2) -> [return: bb5, unwind terminate]; // scope 0 at $DIR/enum_cast.rs:+6:5: +6:6
     }
 
     bb5 (cleanup): {
diff --git a/tests/mir-opt/building/issue_49232.main.built.after.mir b/tests/mir-opt/building/issue_49232.main.built.after.mir
index de5e4c0f6ed..cc135f41721 100644
--- a/tests/mir-opt/building/issue_49232.main.built.after.mir
+++ b/tests/mir-opt/building/issue_49232.main.built.after.mir
@@ -17,7 +17,7 @@ fn main() -> () {
     }
 
     bb1: {
-        falseUnwind -> [real: bb2, cleanup: bb11]; // scope 0 at $DIR/issue_49232.rs:+1:5: +9:6
+        falseUnwind -> [real: bb2, unwind: bb11]; // scope 0 at $DIR/issue_49232.rs:+1:5: +9:6
     }
 
     bb2: {
diff --git a/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir b/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir
index ed72726c5ae..54f0ea2d894 100644
--- a/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir
+++ b/tests/mir-opt/building/uniform_array_move_out.move_out_by_subslice.built.after.mir
@@ -95,15 +95,15 @@ fn move_out_by_subslice() -> () {
     }
 
     bb9 (cleanup): {
-        drop(_1) -> bb12;                // scope 0 at $DIR/uniform_array_move_out.rs:+8:1: +8:2
+        drop(_1) -> [return: bb12, unwind terminate]; // scope 0 at $DIR/uniform_array_move_out.rs:+8:1: +8:2
     }
 
     bb10 (cleanup): {
-        drop(_7) -> bb11;                // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6
+        drop(_7) -> [return: bb11, unwind terminate]; // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6
     }
 
     bb11 (cleanup): {
-        drop(_2) -> bb12;                // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6
+        drop(_2) -> [return: bb12, unwind terminate]; // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6
     }
 
     bb12 (cleanup): {
diff --git a/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir b/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir
index eca874130f6..5090a4ba675 100644
--- a/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir
+++ b/tests/mir-opt/building/uniform_array_move_out.move_out_from_end.built.after.mir
@@ -95,15 +95,15 @@ fn move_out_from_end() -> () {
     }
 
     bb9 (cleanup): {
-        drop(_1) -> bb12;                // scope 0 at $DIR/uniform_array_move_out.rs:+8:1: +8:2
+        drop(_1) -> [return: bb12, unwind terminate]; // scope 0 at $DIR/uniform_array_move_out.rs:+8:1: +8:2
     }
 
     bb10 (cleanup): {
-        drop(_7) -> bb11;                // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6
+        drop(_7) -> [return: bb11, unwind terminate]; // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6
     }
 
     bb11 (cleanup): {
-        drop(_2) -> bb12;                // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6
+        drop(_2) -> [return: bb12, unwind terminate]; // scope 0 at $DIR/uniform_array_move_out.rs:+6:5: +6:6
     }
 
     bb12 (cleanup): {
diff --git a/tests/mir-opt/combine_array_len.rs b/tests/mir-opt/combine_array_len.rs
index 3ef3bd09afd..08c5f1a1fc5 100644
--- a/tests/mir-opt/combine_array_len.rs
+++ b/tests/mir-opt/combine_array_len.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: InstCombine
 // EMIT_MIR combine_array_len.norm2.InstCombine.diff
 
diff --git a/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff b/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff
index 20b0fb9643e..b715a544ffe 100644
--- a/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff
+++ b/tests/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff
@@ -72,7 +72,7 @@
       }
   
       bb4 (cleanup): {
-          drop(_2) -> bb5;                 // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:14: +0:15
+          drop(_2) -> [return: bb5, unwind terminate]; // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:14: +0:15
       }
   
       bb5 (cleanup): {
diff --git a/tests/mir-opt/combine_transmutes.adt_transmutes.InstCombine.diff b/tests/mir-opt/combine_transmutes.adt_transmutes.InstCombine.diff
index c44a14075ef..168e8c61031 100644
--- a/tests/mir-opt/combine_transmutes.adt_transmutes.InstCombine.diff
+++ b/tests/mir-opt/combine_transmutes.adt_transmutes.InstCombine.diff
@@ -128,7 +128,7 @@
           StorageDead(_22);                // scope 10 at $DIR/combine_transmutes.rs:+11:47: +11:48
           StorageLive(_23);                // scope 11 at $DIR/combine_transmutes.rs:+12:9: +12:11
           StorageLive(_24);                // scope 11 at $DIR/combine_transmutes.rs:+12:46: +12:77
-          _24 = MaybeUninit::<String>::uninit() -> bb1; // scope 11 at $DIR/combine_transmutes.rs:+12:46: +12:77
+          _24 = MaybeUninit::<String>::uninit() -> [return: bb1, unwind unreachable]; // scope 11 at $DIR/combine_transmutes.rs:+12:46: +12:77
                                            // mir::Constant
                                            // + span: $DIR/combine_transmutes.rs:46:46: 46:75
                                            // + user_ty: UserType(23)
diff --git a/tests/mir-opt/combine_transmutes.identity_transmutes.InstCombine.diff b/tests/mir-opt/combine_transmutes.identity_transmutes.InstCombine.diff
index c83c9f5acf4..ae1185c7f71 100644
--- a/tests/mir-opt/combine_transmutes.identity_transmutes.InstCombine.diff
+++ b/tests/mir-opt/combine_transmutes.identity_transmutes.InstCombine.diff
@@ -19,7 +19,7 @@
 +         _1 = const 1_i32;                // scope 0 at $DIR/combine_transmutes.rs:+2:14: +2:38
           StorageLive(_2);                 // scope 1 at $DIR/combine_transmutes.rs:+3:9: +3:11
           StorageLive(_3);                 // scope 1 at $DIR/combine_transmutes.rs:+3:46: +3:56
-          _3 = Vec::<i32>::new() -> bb1;   // scope 1 at $DIR/combine_transmutes.rs:+3:46: +3:56
+          _3 = Vec::<i32>::new() -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/combine_transmutes.rs:+3:46: +3:56
                                            // mir::Constant
                                            // + span: $DIR/combine_transmutes.rs:15:46: 15:54
                                            // + user_ty: UserType(0)
@@ -31,7 +31,7 @@
 +         _2 = move _3;                    // scope 1 at $DIR/combine_transmutes.rs:+3:14: +3:57
           StorageDead(_3);                 // scope 1 at $DIR/combine_transmutes.rs:+3:56: +3:57
           _0 = const ();                   // scope 0 at $DIR/combine_transmutes.rs:+0:37: +4:2
-          drop(_2) -> bb2;                 // scope 1 at $DIR/combine_transmutes.rs:+4:1: +4:2
+          drop(_2) -> [return: bb2, unwind unreachable]; // scope 1 at $DIR/combine_transmutes.rs:+4:1: +4:2
       }
   
       bb2: {
diff --git a/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff b/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff
index f6e58955b4f..0411972661e 100644
--- a/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/aggregate.main.ConstProp.diff
@@ -29,7 +29,7 @@
 +         _5 = const 1_u8;                 // scope 1 at $DIR/aggregate.rs:+2:9: +2:10
           _4 = foo(move _5) -> bb1;        // scope 1 at $DIR/aggregate.rs:+2:5: +2:11
                                            // mir::Constant
-                                           // + span: $DIR/aggregate.rs:8:5: 8:8
+                                           // + span: $DIR/aggregate.rs:9:5: 9:8
                                            // + literal: Const { ty: fn(u8) {foo}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir b/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir
index 4706af92cba..05d4bf8b52e 100644
--- a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir
+++ b/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.mir
@@ -25,7 +25,7 @@ fn main() -> () {
         _5 = const 1_u8;                 // scope 1 at $DIR/aggregate.rs:+2:9: +2:10
         _4 = foo(move _5) -> bb1;        // scope 1 at $DIR/aggregate.rs:+2:5: +2:11
                                          // mir::Constant
-                                         // + span: $DIR/aggregate.rs:8:5: 8:8
+                                         // + span: $DIR/aggregate.rs:9:5: 9:8
                                          // + literal: Const { ty: fn(u8) {foo}, val: Value(<ZST>) }
     }
 
diff --git a/tests/mir-opt/const_prop/aggregate.rs b/tests/mir-opt/const_prop/aggregate.rs
index aa123b7a866..ed5a4ab594d 100644
--- a/tests/mir-opt/const_prop/aggregate.rs
+++ b/tests/mir-opt/const_prop/aggregate.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 // compile-flags: -O
 
diff --git a/tests/mir-opt/const_prop/array_index.rs b/tests/mir-opt/const_prop/array_index.rs
index d31c2827b4e..f36cf221348 100644
--- a/tests/mir-opt/const_prop/array_index.rs
+++ b/tests/mir-opt/const_prop/array_index.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 
diff --git a/tests/mir-opt/const_prop/bad_op_div_by_zero.rs b/tests/mir-opt/const_prop/bad_op_div_by_zero.rs
index a6fd325ece0..38f1a993dc0 100644
--- a/tests/mir-opt/const_prop/bad_op_div_by_zero.rs
+++ b/tests/mir-opt/const_prop/bad_op_div_by_zero.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 // EMIT_MIR bad_op_div_by_zero.main.ConstProp.diff
 #[allow(unconditional_panic)]
diff --git a/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs b/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs
index cc16a4a5aa7..a1078472cbf 100644
--- a/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs
+++ b/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // EMIT_MIR bad_op_mod_by_zero.main.ConstProp.diff
 #[allow(unconditional_panic)]
 fn main() {
diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
index 38d402b8f21..e711babf035 100644
--- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
+++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.32bit.diff
@@ -25,7 +25,7 @@
           StorageLive(_2);                 // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
           _8 = const _;                    // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
                                            // mir::Constant
-                                           // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
+                                           // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:6:25: 6:35
                                            // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) }
           _2 = &raw const (*_8);           // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
           _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
index 38d402b8f21..e711babf035 100644
--- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
+++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.ConstProp.64bit.diff
@@ -25,7 +25,7 @@
           StorageLive(_2);                 // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
           _8 = const _;                    // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
                                            // mir::Constant
-                                           // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
+                                           // + span: $DIR/bad_op_unsafe_oob_for_slices.rs:6:25: 6:35
                                            // + literal: Const { ty: &[i32; 3], val: Unevaluated(main, [], Some(promoted[0])) }
           _2 = &raw const (*_8);           // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
           _1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:+1:25: +1:35
diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs
index cf22b06d5e5..3d252f2d221 100644
--- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs
+++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 // EMIT_MIR bad_op_unsafe_oob_for_slices.main.ConstProp.diff
 #[allow(unconditional_panic)]
diff --git a/tests/mir-opt/const_prop/checked_add.rs b/tests/mir-opt/const_prop/checked_add.rs
index b9860da4c82..007defd1037 100644
--- a/tests/mir-opt/const_prop/checked_add.rs
+++ b/tests/mir-opt/const_prop/checked_add.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 // compile-flags: -C overflow-checks=on
 
diff --git a/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff b/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
index bea7114c7df..d75fae30b53 100644
--- a/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
@@ -18,7 +18,7 @@
           StorageLive(_3);                 // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16
           _3 = const _;                    // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16
                                            // mir::Constant
-                                           // + span: $DIR/const_prop_fails_gracefully.rs:8:13: 8:16
+                                           // + span: $DIR/const_prop_fails_gracefully.rs:9:13: 9:16
                                            // + literal: Const { ty: &i32, val: Unevaluated(FOO, [], None) }
           _2 = &raw const (*_3);           // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16
           _1 = move _2 as usize (PointerExposeAddress); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:39
@@ -29,7 +29,7 @@
           _5 = _1;                         // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:10: +3:11
           _4 = read(move _5) -> bb1;       // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:5: +3:12
                                            // mir::Constant
-                                           // + span: $DIR/const_prop_fails_gracefully.rs:9:5: 9:9
+                                           // + span: $DIR/const_prop_fails_gracefully.rs:10:5: 10:9
                                            // + literal: Const { ty: fn(usize) {read}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/const_prop/const_prop_fails_gracefully.rs b/tests/mir-opt/const_prop/const_prop_fails_gracefully.rs
index 0a3dcbd380f..44d4878424d 100644
--- a/tests/mir-opt/const_prop/const_prop_fails_gracefully.rs
+++ b/tests/mir-opt/const_prop/const_prop_fails_gracefully.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 #[inline(never)]
 fn read(_: usize) { }
diff --git a/tests/mir-opt/const_prop/control_flow_simplification.rs b/tests/mir-opt/const_prop/control_flow_simplification.rs
index 7dbe8e7344b..b2ca045e89f 100644
--- a/tests/mir-opt/const_prop/control_flow_simplification.rs
+++ b/tests/mir-opt/const_prop/control_flow_simplification.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 // compile-flags: -Zmir-opt-level=1
 
diff --git a/tests/mir-opt/const_prop/indirect.rs b/tests/mir-opt/const_prop/indirect.rs
index 44916cbfe74..46fd8082d30 100644
--- a/tests/mir-opt/const_prop/indirect.rs
+++ b/tests/mir-opt/const_prop/indirect.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 // compile-flags: -C overflow-checks=on
 
diff --git a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.diff b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.diff
index d03c23a3fb5..0ac7fa43d5b 100644
--- a/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/inherit_overflow.main.ConstProp.diff
@@ -8,7 +8,7 @@
       let mut _3: u8;                      // in scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
       scope 1 {
       }
-      scope 2 (inlined <u8 as Add>::add) { // at $DIR/inherit_overflow.rs:8:13: 8:47
+      scope 2 (inlined <u8 as Add>::add) { // at $DIR/inherit_overflow.rs:9:13: 9:47
           debug self => _2;                // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
           debug other => _3;               // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
           let mut _4: (u8, bool);          // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
diff --git a/tests/mir-opt/const_prop/inherit_overflow.rs b/tests/mir-opt/const_prop/inherit_overflow.rs
index 541a8c5c3af..4e905d00d4d 100644
--- a/tests/mir-opt/const_prop/inherit_overflow.rs
+++ b/tests/mir-opt/const_prop/inherit_overflow.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 // compile-flags: -Zmir-enable-passes=+Inline
 
diff --git a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff
index a4f9003e140..2652694097c 100644
--- a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.diff
@@ -11,7 +11,7 @@
           _2 = (const (), const 0_u8, const 0_u8); // scope 0 at $DIR/issue_66971.rs:+1:12: +1:22
           _1 = encode(move _2) -> bb1;     // scope 0 at $DIR/issue_66971.rs:+1:5: +1:23
                                            // mir::Constant
-                                           // + span: $DIR/issue_66971.rs:17:5: 17:11
+                                           // + span: $DIR/issue_66971.rs:18:5: 18:11
                                            // + literal: Const { ty: fn(((), u8, u8)) {encode}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/const_prop/issue_66971.rs b/tests/mir-opt/const_prop/issue_66971.rs
index 6ca03438ef3..af95c9ca283 100644
--- a/tests/mir-opt/const_prop/issue_66971.rs
+++ b/tests/mir-opt/const_prop/issue_66971.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 // compile-flags: -Z mir-opt-level=3
 
diff --git a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff
index f456a321204..54c9200d672 100644
--- a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.diff
@@ -16,7 +16,7 @@
           StorageDead(_3);                 // scope 0 at $DIR/issue_67019.rs:+1:18: +1:19
           _1 = test(move _2) -> bb1;       // scope 0 at $DIR/issue_67019.rs:+1:5: +1:20
                                            // mir::Constant
-                                           // + span: $DIR/issue_67019.rs:12:5: 12:9
+                                           // + span: $DIR/issue_67019.rs:13:5: 13:9
                                            // + literal: Const { ty: fn(((u8, u8),)) {test}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/const_prop/issue_67019.rs b/tests/mir-opt/const_prop/issue_67019.rs
index ffc6fa1f290..08c7d4805d6 100644
--- a/tests/mir-opt/const_prop/issue_67019.rs
+++ b/tests/mir-opt/const_prop/issue_67019.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 // compile-flags: -Z mir-opt-level=3
 
diff --git a/tests/mir-opt/const_prop/large_array_index.rs b/tests/mir-opt/const_prop/large_array_index.rs
index 48d134376db..073f9849568 100644
--- a/tests/mir-opt/const_prop/large_array_index.rs
+++ b/tests/mir-opt/const_prop/large_array_index.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 
 // EMIT_MIR large_array_index.main.ConstProp.diff
diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff
index 149aa6290d0..75f6ebc58c7 100644
--- a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff
@@ -16,7 +16,7 @@
           StorageLive(_1);                 // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:9: +1:14
           _1 = foo() -> bb1;               // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:29: +1:34
                                            // mir::Constant
-                                           // + span: $DIR/mutable_variable_aggregate_partial_read.rs:6:29: 6:32
+                                           // + span: $DIR/mutable_variable_aggregate_partial_read.rs:7:29: 7:32
                                            // + literal: Const { ty: fn() -> (i32, i32) {foo}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs
index cb59509ff10..70a287cf381 100644
--- a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs
+++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test
 // compile-flags: -O
 
diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff
index 4010dd6c6d0..9582504b25e 100644
--- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff
@@ -26,7 +26,7 @@
           StorageLive(_1);                 // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10
           _1 = foo() -> bb1;               // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:13: +1:18
                                            // mir::Constant
-                                           // + span: $DIR/mutable_variable_unprop_assign.rs:6:13: 6:16
+                                           // + span: $DIR/mutable_variable_unprop_assign.rs:7:13: 7:16
                                            // + literal: Const { ty: fn() -> i32 {foo}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs
index b077cfd3e0a..fabd04e9bd2 100644
--- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs
+++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test
 // compile-flags: -O
 
diff --git a/tests/mir-opt/const_prop/optimizes_into_variable.rs b/tests/mir-opt/const_prop/optimizes_into_variable.rs
index abea07e2025..5ffa153476d 100644
--- a/tests/mir-opt/const_prop/optimizes_into_variable.rs
+++ b/tests/mir-opt/const_prop/optimizes_into_variable.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test
 // compile-flags: -C overflow-checks=on
 
diff --git a/tests/mir-opt/const_prop/repeat.rs b/tests/mir-opt/const_prop/repeat.rs
index 36d9b9fc62d..2f3b7d2c502 100644
--- a/tests/mir-opt/const_prop/repeat.rs
+++ b/tests/mir-opt/const_prop/repeat.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // compile-flags: -O
 
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
diff --git a/tests/mir-opt/const_prop/return_place.rs b/tests/mir-opt/const_prop/return_place.rs
index 06a85369679..ae119df8518 100644
--- a/tests/mir-opt/const_prop/return_place.rs
+++ b/tests/mir-opt/const_prop/return_place.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // compile-flags: -C overflow-checks=on
 
 // EMIT_MIR return_place.add.ConstProp.diff
diff --git a/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff b/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff
index 1151caaabbc..a091b4ace20 100644
--- a/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/scalar_literal_propagation.main.ConstProp.diff
@@ -15,7 +15,7 @@
 -         _2 = consume(_1) -> bb1;         // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15
 +         _2 = consume(const 1_u32) -> bb1; // scope 1 at $DIR/scalar_literal_propagation.rs:+2:5: +2:15
                                            // mir::Constant
-                                           // + span: $DIR/scalar_literal_propagation.rs:4:5: 4:12
+                                           // + span: $DIR/scalar_literal_propagation.rs:5:5: 5:12
                                            // + literal: Const { ty: fn(u32) {consume}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/const_prop/scalar_literal_propagation.rs b/tests/mir-opt/const_prop/scalar_literal_propagation.rs
index 8724e4d5711..e13e352f8a1 100644
--- a/tests/mir-opt/const_prop/scalar_literal_propagation.rs
+++ b/tests/mir-opt/const_prop/scalar_literal_propagation.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // EMIT_MIR scalar_literal_propagation.main.ConstProp.diff
 fn main() {
     let x = 1;
diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
index b99b83b0cba..8bd2b48d6d6 100644
--- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.diff
@@ -20,7 +20,7 @@
           StorageLive(_4);                 // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
           _9 = const _;                    // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
                                            // mir::Constant
-                                           // + span: $DIR/slice_len.rs:7:6: 7:19
+                                           // + span: $DIR/slice_len.rs:8:6: 8:19
                                            // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) }
           _4 = _9;                         // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
           _3 = _4;                         // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
index b99b83b0cba..8bd2b48d6d6 100644
--- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.diff
@@ -20,7 +20,7 @@
           StorageLive(_4);                 // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
           _9 = const _;                    // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
                                            // mir::Constant
-                                           // + span: $DIR/slice_len.rs:7:6: 7:19
+                                           // + span: $DIR/slice_len.rs:8:6: 8:19
                                            // + literal: Const { ty: &[u32; 3], val: Unevaluated(main, [], Some(promoted[0])) }
           _4 = _9;                         // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
           _3 = _4;                         // scope 0 at $DIR/slice_len.rs:+1:6: +1:19
diff --git a/tests/mir-opt/const_prop/slice_len.rs b/tests/mir-opt/const_prop/slice_len.rs
index 8183def0c63..4499c54f264 100644
--- a/tests/mir-opt/const_prop/slice_len.rs
+++ b/tests/mir-opt/const_prop/slice_len.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: ConstProp
 // compile-flags: -Zmir-enable-passes=+InstCombine
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
diff --git a/tests/mir-opt/const_prop/switch_int.main.ConstProp.diff b/tests/mir-opt/const_prop/switch_int.main.ConstProp.diff
index ddc1a4493db..85704c48a2c 100644
--- a/tests/mir-opt/const_prop/switch_int.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/switch_int.main.ConstProp.diff
@@ -15,14 +15,14 @@
       bb1: {
           _0 = foo(const -1_i32) -> bb3;   // scope 0 at $DIR/switch_int.rs:+3:14: +3:21
                                            // mir::Constant
-                                           // + span: $DIR/switch_int.rs:9:14: 9:17
+                                           // + span: $DIR/switch_int.rs:10:14: 10:17
                                            // + literal: Const { ty: fn(i32) {foo}, val: Value(<ZST>) }
       }
   
       bb2: {
           _0 = foo(const 0_i32) -> bb3;    // scope 0 at $DIR/switch_int.rs:+2:14: +2:20
                                            // mir::Constant
-                                           // + span: $DIR/switch_int.rs:8:14: 8:17
+                                           // + span: $DIR/switch_int.rs:9:14: 9:17
                                            // + literal: Const { ty: fn(i32) {foo}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff b/tests/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff
index 09c47ee6e83..0864db22523 100644
--- a/tests/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff
+++ b/tests/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff
@@ -15,14 +15,14 @@
       bb1: {
           _0 = foo(const -1_i32) -> bb3;   // scope 0 at $DIR/switch_int.rs:+3:14: +3:21
                                            // mir::Constant
-                                           // + span: $DIR/switch_int.rs:9:14: 9:17
+                                           // + span: $DIR/switch_int.rs:10:14: 10:17
                                            // + literal: Const { ty: fn(i32) {foo}, val: Value(<ZST>) }
       }
   
       bb2: {
           _0 = foo(const 0_i32) -> bb3;    // scope 0 at $DIR/switch_int.rs:+2:14: +2:20
                                            // mir::Constant
-                                           // + span: $DIR/switch_int.rs:8:14: 8:17
+                                           // + span: $DIR/switch_int.rs:9:14: 9:17
                                            // + literal: Const { ty: fn(i32) {foo}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/const_prop/switch_int.rs b/tests/mir-opt/const_prop/switch_int.rs
index d7319eca18e..2a2322e43a9 100644
--- a/tests/mir-opt/const_prop/switch_int.rs
+++ b/tests/mir-opt/const_prop/switch_int.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 #[inline(never)]
 fn foo(_: i32) { }
 
diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff b/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff
index d370abce45a..12313b6c58d 100644
--- a/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/tuple_literal_propagation.main.ConstProp.diff
@@ -15,7 +15,7 @@
 +         _1 = const (1_u32, 2_u32);       // scope 0 at $DIR/tuple_literal_propagation.rs:+1:13: +1:19
           _2 = consume(_1) -> bb1;         // scope 1 at $DIR/tuple_literal_propagation.rs:+3:5: +3:15
                                            // mir::Constant
-                                           // + span: $DIR/tuple_literal_propagation.rs:5:5: 5:12
+                                           // + span: $DIR/tuple_literal_propagation.rs:6:5: 6:12
                                            // + literal: Const { ty: fn((u32, u32)) {consume}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.rs b/tests/mir-opt/const_prop/tuple_literal_propagation.rs
index e644baec4a8..edd748d00ab 100644
--- a/tests/mir-opt/const_prop/tuple_literal_propagation.rs
+++ b/tests/mir-opt/const_prop/tuple_literal_propagation.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // EMIT_MIR tuple_literal_propagation.main.ConstProp.diff
 fn main() {
     let x = (1, 2);
diff --git a/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.diff b/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.diff
index b183865a9bc..2a0bff57db9 100644
--- a/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/borrowed_local.f.CopyProp.diff
@@ -15,7 +15,7 @@
           _4 = &_3;                        // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
           _0 = cmp_ref(_2, _4) -> bb1;     // scope 0 at $DIR/borrowed_local.rs:+8:13: +8:45
                                            // mir::Constant
-                                           // + span: $DIR/borrowed_local.rs:23:29: 23:36
+                                           // + span: $DIR/borrowed_local.rs:24:29: 24:36
                                            // + literal: Const { ty: for<'a, 'b> fn(&'a u8, &'b u8) -> bool {cmp_ref}, val: Value(<ZST>) }
       }
   
@@ -23,7 +23,7 @@
 -         _0 = opaque::<u8>(_3) -> bb2;    // scope 0 at $DIR/borrowed_local.rs:+12:13: +12:38
 +         _0 = opaque::<u8>(_1) -> bb2;    // scope 0 at $DIR/borrowed_local.rs:+12:13: +12:38
                                            // mir::Constant
-                                           // + span: $DIR/borrowed_local.rs:27:28: 27:34
+                                           // + span: $DIR/borrowed_local.rs:28:28: 28:34
                                            // + literal: Const { ty: fn(u8) -> bool {opaque::<u8>}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/copy-prop/borrowed_local.rs b/tests/mir-opt/copy-prop/borrowed_local.rs
index c4b980e2b35..9186da5af48 100644
--- a/tests/mir-opt/copy-prop/borrowed_local.rs
+++ b/tests/mir-opt/copy-prop/borrowed_local.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: CopyProp
 
 #![feature(custom_mir, core_intrinsics)]
diff --git a/tests/mir-opt/copy-prop/branch.foo.CopyProp.diff b/tests/mir-opt/copy-prop/branch.foo.CopyProp.diff
index 8b116532d9f..b78c19d78d0 100644
--- a/tests/mir-opt/copy-prop/branch.foo.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/branch.foo.CopyProp.diff
@@ -18,7 +18,7 @@
           StorageLive(_1);                 // scope 0 at $DIR/branch.rs:+1:9: +1:10
           _1 = val() -> bb1;               // scope 0 at $DIR/branch.rs:+1:13: +1:18
                                            // mir::Constant
-                                           // + span: $DIR/branch.rs:13:13: 13:16
+                                           // + span: $DIR/branch.rs:14:13: 14:16
                                            // + literal: Const { ty: fn() -> i32 {val}, val: Value(<ZST>) }
       }
   
@@ -27,7 +27,7 @@
           StorageLive(_3);                 // scope 1 at $DIR/branch.rs:+3:16: +3:22
           _3 = cond() -> bb2;              // scope 1 at $DIR/branch.rs:+3:16: +3:22
                                            // mir::Constant
-                                           // + span: $DIR/branch.rs:15:16: 15:20
+                                           // + span: $DIR/branch.rs:16:16: 16:20
                                            // + literal: Const { ty: fn() -> bool {cond}, val: Value(<ZST>) }
       }
   
@@ -44,7 +44,7 @@
           StorageLive(_4);                 // scope 1 at $DIR/branch.rs:+6:9: +6:14
           _4 = val() -> bb5;               // scope 1 at $DIR/branch.rs:+6:9: +6:14
                                            // mir::Constant
-                                           // + span: $DIR/branch.rs:18:9: 18:12
+                                           // + span: $DIR/branch.rs:19:9: 19:12
                                            // + literal: Const { ty: fn() -> i32 {val}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/copy-prop/branch.rs b/tests/mir-opt/copy-prop/branch.rs
index 50b1e00fad4..0a2e1694634 100644
--- a/tests/mir-opt/copy-prop/branch.rs
+++ b/tests/mir-opt/copy-prop/branch.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 //! Tests that we bail out when there are multiple assignments to the same local.
 // unit-test: CopyProp
 fn val() -> i32 {
diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.diff
index ac4e9a2bfa7..24bca32207f 100644
--- a/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/copy_propagation_arg.bar.CopyProp.diff
@@ -13,7 +13,7 @@
           _3 = _1;                         // scope 0 at $DIR/copy_propagation_arg.rs:+1:11: +1:12
           _2 = dummy(move _3) -> bb1;      // scope 0 at $DIR/copy_propagation_arg.rs:+1:5: +1:13
                                            // mir::Constant
-                                           // + span: $DIR/copy_propagation_arg.rs:16:5: 16:10
+                                           // + span: $DIR/copy_propagation_arg.rs:17:5: 17:10
                                            // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.diff b/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.diff
index 0a3e985e7c2..87708f34005 100644
--- a/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/copy_propagation_arg.foo.CopyProp.diff
@@ -13,7 +13,7 @@
           _3 = _1;                         // scope 0 at $DIR/copy_propagation_arg.rs:+2:15: +2:16
           _2 = dummy(move _3) -> bb1;      // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:17
                                            // mir::Constant
-                                           // + span: $DIR/copy_propagation_arg.rs:11:9: 11:14
+                                           // + span: $DIR/copy_propagation_arg.rs:12:9: 12:14
                                            // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/copy-prop/copy_propagation_arg.rs b/tests/mir-opt/copy-prop/copy_propagation_arg.rs
index cc98985f1fd..1b65dcb01ed 100644
--- a/tests/mir-opt/copy-prop/copy_propagation_arg.rs
+++ b/tests/mir-opt/copy-prop/copy_propagation_arg.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Check that CopyProp does not propagate an assignment to a function argument
 // (doing so can break usages of the original argument value)
 // unit-test: CopyProp
diff --git a/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.diff b/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.diff
index 6ca73ffdde2..160f47bdd8f 100644
--- a/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/custom_move_arg.f.CopyProp.diff
@@ -11,7 +11,7 @@
 -         _0 = opaque::<NotCopy>(move _1) -> bb1; // scope 0 at $DIR/custom_move_arg.rs:+3:9: +3:41
 +         _0 = opaque::<NotCopy>(_1) -> bb1; // scope 0 at $DIR/custom_move_arg.rs:+3:9: +3:41
                                            // mir::Constant
-                                           // + span: $DIR/custom_move_arg.rs:15:24: 15:30
+                                           // + span: $DIR/custom_move_arg.rs:16:24: 16:30
                                            // + literal: Const { ty: fn(NotCopy) {opaque::<NotCopy>}, val: Value(<ZST>) }
       }
   
@@ -20,7 +20,7 @@
 -         _0 = opaque::<NotCopy>(_3) -> bb2; // scope 0 at $DIR/custom_move_arg.rs:+7:9: +7:35
 +         _0 = opaque::<NotCopy>(_1) -> bb2; // scope 0 at $DIR/custom_move_arg.rs:+7:9: +7:35
                                            // mir::Constant
-                                           // + span: $DIR/custom_move_arg.rs:19:24: 19:30
+                                           // + span: $DIR/custom_move_arg.rs:20:24: 20:30
                                            // + literal: Const { ty: fn(NotCopy) {opaque::<NotCopy>}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/copy-prop/custom_move_arg.rs b/tests/mir-opt/copy-prop/custom_move_arg.rs
index 4a591146e61..29c368df82d 100644
--- a/tests/mir-opt/copy-prop/custom_move_arg.rs
+++ b/tests/mir-opt/copy-prop/custom_move_arg.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: CopyProp
 
 #![feature(custom_mir, core_intrinsics)]
diff --git a/tests/mir-opt/copy-prop/cycle.main.CopyProp.diff b/tests/mir-opt/copy-prop/cycle.main.CopyProp.diff
index 3e61869e82f..23d92ed1ac5 100644
--- a/tests/mir-opt/copy-prop/cycle.main.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/cycle.main.CopyProp.diff
@@ -24,7 +24,7 @@
           StorageLive(_1);                 // scope 0 at $DIR/cycle.rs:+1:9: +1:14
           _1 = val() -> bb1;               // scope 0 at $DIR/cycle.rs:+1:17: +1:22
                                            // mir::Constant
-                                           // + span: $DIR/cycle.rs:9:17: 9:20
+                                           // + span: $DIR/cycle.rs:10:17: 10:20
                                            // + literal: Const { ty: fn() -> i32 {val}, val: Value(<ZST>) }
       }
   
@@ -43,7 +43,7 @@
           _6 = _1;                         // scope 3 at $DIR/cycle.rs:+6:10: +6:11
           _5 = std::mem::drop::<i32>(move _6) -> bb2; // scope 3 at $DIR/cycle.rs:+6:5: +6:12
                                            // mir::Constant
-                                           // + span: $DIR/cycle.rs:14:5: 14:9
+                                           // + span: $DIR/cycle.rs:15:5: 15:9
                                            // + literal: Const { ty: fn(i32) {std::mem::drop::<i32>}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/copy-prop/cycle.rs b/tests/mir-opt/copy-prop/cycle.rs
index b74c397269d..da70f6bec2e 100644
--- a/tests/mir-opt/copy-prop/cycle.rs
+++ b/tests/mir-opt/copy-prop/cycle.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 //! Tests that cyclic assignments don't hang CopyProp, and result in reasonable code.
 // unit-test: CopyProp
 fn val() -> i32 {
diff --git a/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir
index d48b04e2de2..c56418d8893 100644
--- a/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir
+++ b/tests/mir-opt/copy-prop/dead_stores_79191.f.CopyProp.after.mir
@@ -18,7 +18,7 @@ fn f(_1: usize) -> usize {
         _4 = _1;                         // scope 1 at $DIR/dead_stores_79191.rs:+4:8: +4:9
         _0 = id::<usize>(move _4) -> bb1; // scope 1 at $DIR/dead_stores_79191.rs:+4:5: +4:10
                                          // mir::Constant
-                                         // + span: $DIR/dead_stores_79191.rs:12:5: 12:7
+                                         // + span: $DIR/dead_stores_79191.rs:13:5: 13:7
                                          // + literal: Const { ty: fn(usize) -> usize {id::<usize>}, val: Value(<ZST>) }
     }
 
diff --git a/tests/mir-opt/copy-prop/dead_stores_79191.rs b/tests/mir-opt/copy-prop/dead_stores_79191.rs
index e3493b8b7a1..84453c55e3e 100644
--- a/tests/mir-opt/copy-prop/dead_stores_79191.rs
+++ b/tests/mir-opt/copy-prop/dead_stores_79191.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: CopyProp
 
 fn id<T>(x: T) -> T {
diff --git a/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir
index 727791f50a4..f355421732e 100644
--- a/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir
+++ b/tests/mir-opt/copy-prop/dead_stores_better.f.CopyProp.after.mir
@@ -18,7 +18,7 @@ fn f(_1: usize) -> usize {
         _4 = _1;                         // scope 1 at $DIR/dead_stores_better.rs:+4:8: +4:9
         _0 = id::<usize>(move _4) -> bb1; // scope 1 at $DIR/dead_stores_better.rs:+4:5: +4:10
                                          // mir::Constant
-                                         // + span: $DIR/dead_stores_better.rs:16:5: 16:7
+                                         // + span: $DIR/dead_stores_better.rs:17:5: 17:7
                                          // + literal: Const { ty: fn(usize) -> usize {id::<usize>}, val: Value(<ZST>) }
     }
 
diff --git a/tests/mir-opt/copy-prop/dead_stores_better.rs b/tests/mir-opt/copy-prop/dead_stores_better.rs
index 8465b3c9853..87b916fd3ff 100644
--- a/tests/mir-opt/copy-prop/dead_stores_better.rs
+++ b/tests/mir-opt/copy-prop/dead_stores_better.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // This is a copy of the `dead_stores_79191` test, except that we turn on DSE. This demonstrates
 // that that pass enables this one to do more optimizations.
 
diff --git a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff
index 97d0a01e00b..e09ccb83119 100644
--- a/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/issue_107511.main.CopyProp.diff
@@ -51,7 +51,7 @@
           StorageDead(_7);                 // scope 2 at $DIR/issue_107511.rs:+6:17: +6:18
           _5 = core::slice::<impl [i32]>::len(move _6) -> bb1; // scope 2 at $DIR/issue_107511.rs:+6:17: +6:24
                                            // mir::Constant
-                                           // + span: $DIR/issue_107511.rs:10:19: 10:22
+                                           // + span: $DIR/issue_107511.rs:11:19: 11:22
                                            // + literal: Const { ty: for<'a> fn(&'a [i32]) -> usize {core::slice::<impl [i32]>::len}, val: Value(<ZST>) }
       }
   
@@ -61,7 +61,7 @@
           StorageDead(_5);                 // scope 2 at $DIR/issue_107511.rs:+6:23: +6:24
           _3 = <std::ops::Range<usize> as IntoIterator>::into_iter(move _4) -> bb2; // scope 2 at $DIR/issue_107511.rs:+6:14: +6:24
                                            // mir::Constant
-                                           // + span: $DIR/issue_107511.rs:10:14: 10:24
+                                           // + span: $DIR/issue_107511.rs:11:14: 11:24
                                            // + literal: Const { ty: fn(std::ops::Range<usize>) -> <std::ops::Range<usize> as IntoIterator>::IntoIter {<std::ops::Range<usize> as IntoIterator>::into_iter}, val: Value(<ZST>) }
       }
   
@@ -81,7 +81,7 @@
           _12 = &mut (*_13);               // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
           _11 = <std::ops::Range<usize> as Iterator>::next(move _12) -> bb4; // scope 3 at $DIR/issue_107511.rs:+6:14: +6:24
                                            // mir::Constant
-                                           // + span: $DIR/issue_107511.rs:10:14: 10:24
+                                           // + span: $DIR/issue_107511.rs:11:14: 11:24
                                            // + literal: Const { ty: for<'a> fn(&'a mut std::ops::Range<usize>) -> Option<<std::ops::Range<usize> as Iterator>::Item> {<std::ops::Range<usize> as Iterator>::next}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/copy-prop/issue_107511.rs b/tests/mir-opt/copy-prop/issue_107511.rs
index d593f2872ea..2b00ff15581 100644
--- a/tests/mir-opt/copy-prop/issue_107511.rs
+++ b/tests/mir-opt/copy-prop/issue_107511.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: CopyProp
 
 // EMIT_MIR issue_107511.main.CopyProp.diff
diff --git a/tests/mir-opt/copy-prop/move_arg.f.CopyProp.diff b/tests/mir-opt/copy-prop/move_arg.f.CopyProp.diff
index d76bf1cfe7e..650bd66a7d7 100644
--- a/tests/mir-opt/copy-prop/move_arg.f.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/move_arg.f.CopyProp.diff
@@ -24,7 +24,7 @@
 -         _3 = g::<T>(move _4, move _5) -> bb1; // scope 1 at $DIR/move_arg.rs:+2:5: +2:12
 +         _3 = g::<T>(_1, _1) -> bb1;      // scope 1 at $DIR/move_arg.rs:+2:5: +2:12
                                            // mir::Constant
-                                           // + span: $DIR/move_arg.rs:7:5: 7:6
+                                           // + span: $DIR/move_arg.rs:8:5: 8:6
                                            // + literal: Const { ty: fn(T, T) {g::<T>}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/copy-prop/move_arg.rs b/tests/mir-opt/copy-prop/move_arg.rs
index 40ae1d8f466..f88d9a9e74b 100644
--- a/tests/mir-opt/copy-prop/move_arg.rs
+++ b/tests/mir-opt/copy-prop/move_arg.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Test that we do not move multiple times from the same local.
 // unit-test: CopyProp
 
diff --git a/tests/mir-opt/copy-prop/move_projection.f.CopyProp.diff b/tests/mir-opt/copy-prop/move_projection.f.CopyProp.diff
index 02308beb88a..beb85d68a66 100644
--- a/tests/mir-opt/copy-prop/move_projection.f.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/move_projection.f.CopyProp.diff
@@ -13,14 +13,14 @@
 +         _3 = (_1.0: u8);                 // scope 0 at $SRC_DIR/core/src/intrinsics/mir.rs:LL:COL
 +         _0 = opaque::<Foo>(_1) -> bb1;   // scope 0 at $DIR/move_projection.rs:+6:13: +6:44
                                            // mir::Constant
-                                           // + span: $DIR/move_projection.rs:19:28: 19:34
+                                           // + span: $DIR/move_projection.rs:20:28: 20:34
                                            // + literal: Const { ty: fn(Foo) -> bool {opaque::<Foo>}, val: Value(<ZST>) }
       }
   
       bb1: {
           _0 = opaque::<u8>(move _3) -> bb2; // scope 0 at $DIR/move_projection.rs:+9:13: +9:44
                                            // mir::Constant
-                                           // + span: $DIR/move_projection.rs:22:28: 22:34
+                                           // + span: $DIR/move_projection.rs:23:28: 23:34
                                            // + literal: Const { ty: fn(u8) -> bool {opaque::<u8>}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/copy-prop/move_projection.rs b/tests/mir-opt/copy-prop/move_projection.rs
index 2a1bbae99a4..c158c69e0cf 100644
--- a/tests/mir-opt/copy-prop/move_projection.rs
+++ b/tests/mir-opt/copy-prop/move_projection.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: CopyProp
 
 #![feature(custom_mir, core_intrinsics)]
diff --git a/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.diff b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.diff
index 6c32b675a5b..b4a24824566 100644
--- a/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/reborrow.demiraw.CopyProp.diff
@@ -39,7 +39,7 @@
 -         _6 = opaque::<*mut u8>(move _7) -> bb1; // scope 4 at $DIR/reborrow.rs:+4:5: +4:14
 +         _6 = opaque::<*mut u8>(_2) -> bb1; // scope 4 at $DIR/reborrow.rs:+4:5: +4:14
                                            // mir::Constant
-                                           // + span: $DIR/reborrow.rs:38:5: 38:11
+                                           // + span: $DIR/reborrow.rs:39:5: 39:11
                                            // + literal: Const { ty: fn(*mut u8) {opaque::<*mut u8>}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.diff b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.diff
index 2f1b522c2ec..a6a6c05b24a 100644
--- a/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/reborrow.miraw.CopyProp.diff
@@ -35,7 +35,7 @@
 -         _5 = opaque::<*mut u8>(move _6) -> bb1; // scope 4 at $DIR/reborrow.rs:+4:5: +4:14
 +         _5 = opaque::<*mut u8>(_2) -> bb1; // scope 4 at $DIR/reborrow.rs:+4:5: +4:14
                                            // mir::Constant
-                                           // + span: $DIR/reborrow.rs:30:5: 30:11
+                                           // + span: $DIR/reborrow.rs:31:5: 31:11
                                            // + literal: Const { ty: fn(*mut u8) {opaque::<*mut u8>}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.diff b/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.diff
index 9b580c1f4e1..f3d26cc6e2b 100644
--- a/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/reborrow.remut.CopyProp.diff
@@ -33,7 +33,7 @@
 -         _5 = opaque::<&mut u8>(move _6) -> bb1; // scope 3 at $DIR/reborrow.rs:+4:5: +4:14
 +         _5 = opaque::<&mut u8>(move _2) -> bb1; // scope 3 at $DIR/reborrow.rs:+4:5: +4:14
                                            // mir::Constant
-                                           // + span: $DIR/reborrow.rs:14:5: 14:11
+                                           // + span: $DIR/reborrow.rs:15:5: 15:11
                                            // + literal: Const { ty: fn(&mut u8) {opaque::<&mut u8>}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.diff b/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.diff
index cff4a176098..63e42b4dc77 100644
--- a/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.diff
+++ b/tests/mir-opt/copy-prop/reborrow.reraw.CopyProp.diff
@@ -33,7 +33,7 @@
 -         _5 = opaque::<&mut u8>(move _6) -> bb1; // scope 3 at $DIR/reborrow.rs:+4:5: +4:14
 +         _5 = opaque::<&mut u8>(move _2) -> bb1; // scope 3 at $DIR/reborrow.rs:+4:5: +4:14
                                            // mir::Constant
-                                           // + span: $DIR/reborrow.rs:22:5: 22:11
+                                           // + span: $DIR/reborrow.rs:23:5: 23:11
                                            // + literal: Const { ty: fn(&mut u8) {opaque::<&mut u8>}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/copy-prop/reborrow.rs b/tests/mir-opt/copy-prop/reborrow.rs
index c2926b8fa51..91b77966ba8 100644
--- a/tests/mir-opt/copy-prop/reborrow.rs
+++ b/tests/mir-opt/copy-prop/reborrow.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Check that CopyProp considers reborrows as not mutating the pointer.
 // unit-test: CopyProp
 
diff --git a/tests/mir-opt/dataflow-const-prop/checked.rs b/tests/mir-opt/dataflow-const-prop/checked.rs
index 0738a4ee53b..0f9f5a97fac 100644
--- a/tests/mir-opt/dataflow-const-prop/checked.rs
+++ b/tests/mir-opt/dataflow-const-prop/checked.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: DataflowConstProp
 // compile-flags: -Coverflow-checks=on
 
diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff
index 29781e9ce18..1edcc28e68c 100644
--- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff
+++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.main.DataflowConstProp.diff
@@ -8,7 +8,7 @@
       let mut _3: u8;                      // in scope 0 at $DIR/inherit_overflow.rs:+3:13: +3:47
       scope 1 {
       }
-      scope 2 (inlined <u8 as Add>::add) { // at $DIR/inherit_overflow.rs:8:13: 8:47
+      scope 2 (inlined <u8 as Add>::add) { // at $DIR/inherit_overflow.rs:9:13: 9:47
           debug self => _2;                // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
           debug other => _3;               // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
           let mut _4: (u8, bool);          // in scope 2 at $SRC_DIR/core/src/ops/arith.rs:LL:COL
diff --git a/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs b/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs
index f4aba60f0c8..90349d5270c 100644
--- a/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs
+++ b/tests/mir-opt/dataflow-const-prop/inherit_overflow.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: DataflowConstProp
 // compile-flags: -Zmir-enable-passes=+Inline
 
diff --git a/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff
index 158f187f157..70ef17afd65 100644
--- a/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff
+++ b/tests/mir-opt/dataflow-const-prop/ref_without_sb.main.DataflowConstProp.diff
@@ -26,7 +26,7 @@
           _3 = &(*_4);                     // scope 1 at $DIR/ref_without_sb.rs:+2:12: +2:14
           _2 = escape::<i32>(move _3) -> bb1; // scope 1 at $DIR/ref_without_sb.rs:+2:5: +2:15
                                            // mir::Constant
-                                           // + span: $DIR/ref_without_sb.rs:12:5: 12:11
+                                           // + span: $DIR/ref_without_sb.rs:13:5: 13:11
                                            // + literal: Const { ty: for<'a> fn(&'a i32) {escape::<i32>}, val: Value(<ZST>) }
       }
   
@@ -38,7 +38,7 @@
           StorageLive(_5);                 // scope 1 at $DIR/ref_without_sb.rs:+4:5: +4:20
           _5 = some_function() -> bb2;     // scope 1 at $DIR/ref_without_sb.rs:+4:5: +4:20
                                            // mir::Constant
-                                           // + span: $DIR/ref_without_sb.rs:14:5: 14:18
+                                           // + span: $DIR/ref_without_sb.rs:15:5: 15:18
                                            // + literal: Const { ty: fn() {some_function}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs b/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs
index 2fd480b0968..f53de3cf2d4 100644
--- a/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs
+++ b/tests/mir-opt/dataflow-const-prop/ref_without_sb.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: DataflowConstProp
 
 #[inline(never)]
diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff
index 004643e36f1..6ca569f3d8e 100644
--- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff
+++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.main.DataflowConstProp.diff
@@ -32,7 +32,7 @@
           _5 = _3;                         // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:11
           _4 = ptr::mut_ptr::<impl *mut u8>::add(move _5, const 1_usize) -> bb1; // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:18
                                            // mir::Constant
-                                           // + span: $DIR/sibling_ptr.rs:15:12: 15:15
+                                           // + span: $DIR/sibling_ptr.rs:16:12: 16:15
                                            // + literal: Const { ty: unsafe fn(*mut u8, usize) -> *mut u8 {ptr::mut_ptr::<impl *mut u8>::add}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs b/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs
index 6dfb3a4ed30..81fc3c2f49c 100644
--- a/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs
+++ b/tests/mir-opt/dataflow-const-prop/sibling_ptr.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // This attempts to modify `x.1` via a pointer derived from `addr_of_mut!(x.0)`.
 // According to Miri, that is UB. However, T-opsem has not finalized that
 // decision and as such we cannot rely on it in optimizations. Consequently,
diff --git a/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff b/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff
index 8018400e798..9854beaeb21 100644
--- a/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff
+++ b/tests/mir-opt/dataflow-const-prop/terminator.main.DataflowConstProp.diff
@@ -25,7 +25,7 @@
 -         _2 = foo(move _3) -> bb1;        // scope 1 at $DIR/terminator.rs:+3:5: +3:15
 +         _2 = foo(const 2_i32) -> bb1;    // scope 1 at $DIR/terminator.rs:+3:5: +3:15
                                            // mir::Constant
-                                           // + span: $DIR/terminator.rs:9:5: 9:8
+                                           // + span: $DIR/terminator.rs:10:5: 10:8
                                            // + literal: Const { ty: fn(i32) {foo}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/dataflow-const-prop/terminator.rs b/tests/mir-opt/dataflow-const-prop/terminator.rs
index d151f666a2d..4f001df35f1 100644
--- a/tests/mir-opt/dataflow-const-prop/terminator.rs
+++ b/tests/mir-opt/dataflow-const-prop/terminator.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: DataflowConstProp
 
 fn foo(n: i32) {}
diff --git a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff
index cd3b792fb75..2776ff51d85 100644
--- a/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff
+++ b/tests/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff
@@ -32,7 +32,7 @@
 +         StorageLive(_4);                 // scope 0 at $DIR/cycle.rs:+3:11: +3:17
 +         _4 = cond() -> bb2;              // scope 0 at $DIR/cycle.rs:+3:11: +3:17
                                            // mir::Constant
-                                           // + span: $DIR/cycle.rs:12:11: 12:15
+                                           // + span: $DIR/cycle.rs:13:11: 13:15
                                            // + literal: Const { ty: fn() -> bool {cond}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/dead-store-elimination/cycle.rs b/tests/mir-opt/dead-store-elimination/cycle.rs
index b35ce0bcb5a..570bfe84d10 100644
--- a/tests/mir-opt/dead-store-elimination/cycle.rs
+++ b/tests/mir-opt/dead-store-elimination/cycle.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: DeadStoreElimination
 
 #[inline(never)]
diff --git a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff
index 3b1f81175cb..c4ebf1ca834 100644
--- a/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff
+++ b/tests/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff
@@ -19,7 +19,7 @@
           _3 = &(*_1);                     // scope 0 at $DIR/deduplicate_blocks.rs:+1:11: +1:23
           _2 = core::str::<impl str>::as_bytes(move _3) -> bb1; // scope 0 at $DIR/deduplicate_blocks.rs:+1:11: +1:23
                                            // mir::Constant
-                                           // + span: $DIR/deduplicate_blocks.rs:5:13: 5:21
+                                           // + span: $DIR/deduplicate_blocks.rs:6:13: 6:21
                                            // + literal: Const { ty: for<'a> fn(&'a str) -> &'a [u8] {core::str::<impl str>::as_bytes}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/deduplicate_blocks.rs b/tests/mir-opt/deduplicate_blocks.rs
index 2b9eed99ecd..46012e19aa4 100644
--- a/tests/mir-opt/deduplicate_blocks.rs
+++ b/tests/mir-opt/deduplicate_blocks.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: DeduplicateBlocks
 
 // EMIT_MIR deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff
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 9597a0c835f..97826ed19a2 100644
--- a/tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir
+++ b/tests/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir
@@ -25,19 +25,19 @@ fn foo(_1: Option<String>) -> i32 {
         _7 = const false;                // scope 0 at $DIR/string.rs:+3:9: +3:10
         _6 = move _1;                    // scope 0 at $DIR/string.rs:+3:9: +3:10
         _0 = const 4321_i32;             // scope 1 at $DIR/string.rs:+3:14: +3:18
-        drop(_6) -> bb6;                 // scope 0 at $DIR/string.rs:+3:17: +3:18
+        drop(_6) -> [return: bb6, unwind unreachable]; // scope 0 at $DIR/string.rs:+3:17: +3:18
     }
 
     bb2: {
         _2 = &((_1 as Some).0: std::string::String); // scope 0 at $DIR/string.rs:+2:14: +2:17
-        _3 = <String as Deref>::deref(move _2) -> bb3; // scope 0 at $DIR/string.rs:+2:14: +2:17
+        _3 = <String as Deref>::deref(move _2) -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/string.rs:+2:14: +2:17
                                          // mir::Constant
                                          // + span: $DIR/string.rs:9:14: 9:17
                                          // + literal: Const { ty: for<'a> fn(&'a String) -> &'a <String as Deref>::Target {<String as Deref>::deref}, val: Value(<ZST>) }
     }
 
     bb3: {
-        _4 = <str as PartialEq>::eq(_3, const "a") -> bb4; // scope 0 at $DIR/string.rs:+2:14: +2:17
+        _4 = <str as PartialEq>::eq(_3, const "a") -> [return: bb4, unwind unreachable]; // scope 0 at $DIR/string.rs:+2:14: +2:17
                                          // mir::Constant
                                          // + span: $DIR/string.rs:9:14: 9:17
                                          // + literal: Const { ty: for<'a, 'b> fn(&'a str, &'b str) -> bool {<str as PartialEq>::eq}, val: Value(<ZST>) }
@@ -65,7 +65,7 @@ fn foo(_1: Option<String>) -> i32 {
     }
 
     bb8: {
-        drop(_1) -> bb7;                 // scope 0 at $DIR/string.rs:+5:1: +5:2
+        drop(_1) -> [return: bb7, unwind unreachable]; // scope 0 at $DIR/string.rs:+5:1: +5:2
     }
 
     bb9: {
diff --git a/tests/mir-opt/derefer_inline_test.main.Derefer.diff b/tests/mir-opt/derefer_inline_test.main.Derefer.diff
index ec9cbb25322..426d4fb213c 100644
--- a/tests/mir-opt/derefer_inline_test.main.Derefer.diff
+++ b/tests/mir-opt/derefer_inline_test.main.Derefer.diff
@@ -35,7 +35,7 @@
       }
   
       bb4 (cleanup): {
-          drop(_2) -> bb5;                 // scope 0 at $DIR/derefer_inline_test.rs:+1:17: +1:18
+          drop(_2) -> [return: bb5, unwind terminate]; // scope 0 at $DIR/derefer_inline_test.rs:+1:17: +1:18
       }
   
       bb5 (cleanup): {
diff --git a/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff b/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff
index 9c729663265..b7416d389ef 100644
--- a/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff
+++ b/tests/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff
@@ -22,7 +22,7 @@
 +         nop;                             // scope 0 at $DIR/branch.rs:+1:9: +1:10
 +         _0 = val() -> bb1;               // scope 0 at $DIR/branch.rs:+1:13: +1:18
                                            // mir::Constant
-                                           // + span: $DIR/branch.rs:13:13: 13:16
+                                           // + span: $DIR/branch.rs:14:13: 14:16
                                            // + literal: Const { ty: fn() -> i32 {val}, val: Value(<ZST>) }
       }
   
@@ -32,7 +32,7 @@
           StorageLive(_3);                 // scope 1 at $DIR/branch.rs:+3:16: +3:22
           _3 = cond() -> bb2;              // scope 1 at $DIR/branch.rs:+3:16: +3:22
                                            // mir::Constant
-                                           // + span: $DIR/branch.rs:15:16: 15:20
+                                           // + span: $DIR/branch.rs:16:16: 16:20
                                            // + literal: Const { ty: fn() -> bool {cond}, val: Value(<ZST>) }
       }
   
@@ -50,7 +50,7 @@
           StorageLive(_4);                 // scope 1 at $DIR/branch.rs:+6:9: +6:14
           _4 = val() -> bb5;               // scope 1 at $DIR/branch.rs:+6:9: +6:14
                                            // mir::Constant
-                                           // + span: $DIR/branch.rs:18:9: 18:12
+                                           // + span: $DIR/branch.rs:19:9: 19:12
                                            // + literal: Const { ty: fn() -> i32 {val}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/dest-prop/branch.rs b/tests/mir-opt/dest-prop/branch.rs
index 898c908b18c..7e4276e6692 100644
--- a/tests/mir-opt/dest-prop/branch.rs
+++ b/tests/mir-opt/dest-prop/branch.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 //! Tests that assignment in both branches of an `if` are eliminated.
 // unit-test: DestinationPropagation
 fn val() -> i32 {
diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff b/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff
index 298991b5ad1..a61e741f73d 100644
--- a/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff
+++ b/tests/mir-opt/dest-prop/copy_propagation_arg.bar.DestinationPropagation.diff
@@ -16,7 +16,7 @@
 +         nop;                             // scope 0 at $DIR/copy_propagation_arg.rs:+1:11: +1:12
 +         _2 = dummy(move _1) -> bb1;      // scope 0 at $DIR/copy_propagation_arg.rs:+1:5: +1:13
                                            // mir::Constant
-                                           // + span: $DIR/copy_propagation_arg.rs:16:5: 16:10
+                                           // + span: $DIR/copy_propagation_arg.rs:17:5: 17:10
                                            // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff b/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff
index d37a9f71d3e..c7fbecac5c4 100644
--- a/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff
+++ b/tests/mir-opt/dest-prop/copy_propagation_arg.foo.DestinationPropagation.diff
@@ -15,7 +15,7 @@
 -         _2 = dummy(move _3) -> bb1;      // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:17
 +         _1 = dummy(move _3) -> bb1;      // scope 0 at $DIR/copy_propagation_arg.rs:+2:9: +2:17
                                            // mir::Constant
-                                           // + span: $DIR/copy_propagation_arg.rs:11:9: 11:14
+                                           // + span: $DIR/copy_propagation_arg.rs:12:9: 12:14
                                            // + literal: Const { ty: fn(u8) -> u8 {dummy}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/dest-prop/copy_propagation_arg.rs b/tests/mir-opt/dest-prop/copy_propagation_arg.rs
index 31be6c93139..57cb328c231 100644
--- a/tests/mir-opt/dest-prop/copy_propagation_arg.rs
+++ b/tests/mir-opt/dest-prop/copy_propagation_arg.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Check that DestinationPropagation does not propagate an assignment to a function argument
 // (doing so can break usages of the original argument value)
 // unit-test: DestinationPropagation
diff --git a/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff b/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff
index cfc203c5f89..b06f069a2e4 100644
--- a/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff
+++ b/tests/mir-opt/dest-prop/cycle.main.DestinationPropagation.diff
@@ -28,7 +28,7 @@
 +         nop;                             // scope 0 at $DIR/cycle.rs:+1:9: +1:14
 +         _6 = val() -> bb1;               // scope 0 at $DIR/cycle.rs:+1:17: +1:22
                                            // mir::Constant
-                                           // + span: $DIR/cycle.rs:9:17: 9:20
+                                           // + span: $DIR/cycle.rs:10:17: 10:20
                                            // + literal: Const { ty: fn() -> i32 {val}, val: Value(<ZST>) }
       }
   
@@ -56,7 +56,7 @@
 +         nop;                             // scope 3 at $DIR/cycle.rs:+6:10: +6:11
           _5 = std::mem::drop::<i32>(move _6) -> bb2; // scope 3 at $DIR/cycle.rs:+6:5: +6:12
                                            // mir::Constant
-                                           // + span: $DIR/cycle.rs:14:5: 14:9
+                                           // + span: $DIR/cycle.rs:15:5: 15:9
                                            // + literal: Const { ty: fn(i32) {std::mem::drop::<i32>}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/dest-prop/cycle.rs b/tests/mir-opt/dest-prop/cycle.rs
index 6182878f341..3aea19d80dc 100644
--- a/tests/mir-opt/dest-prop/cycle.rs
+++ b/tests/mir-opt/dest-prop/cycle.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 //! Tests that cyclic assignments don't hang DestinationPropagation, and result in reasonable code.
 // unit-test: DestinationPropagation
 fn val() -> i32 {
diff --git a/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.mir b/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.mir
index 63cac133b73..b9d4b59d2f7 100644
--- a/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.mir
+++ b/tests/mir-opt/dest-prop/dead_stores_79191.f.DestinationPropagation.after.mir
@@ -22,7 +22,7 @@ fn f(_1: usize) -> usize {
         nop;                             // scope 1 at $DIR/dead_stores_79191.rs:+4:8: +4:9
         _0 = id::<usize>(move _1) -> bb1; // scope 1 at $DIR/dead_stores_79191.rs:+4:5: +4:10
                                          // mir::Constant
-                                         // + span: $DIR/dead_stores_79191.rs:12:5: 12:7
+                                         // + span: $DIR/dead_stores_79191.rs:13:5: 13:7
                                          // + literal: Const { ty: fn(usize) -> usize {id::<usize>}, val: Value(<ZST>) }
     }
 
diff --git a/tests/mir-opt/dest-prop/dead_stores_79191.rs b/tests/mir-opt/dest-prop/dead_stores_79191.rs
index 43e0bf66418..9d4814838d4 100644
--- a/tests/mir-opt/dest-prop/dead_stores_79191.rs
+++ b/tests/mir-opt/dest-prop/dead_stores_79191.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: DestinationPropagation
 
 fn id<T>(x: T) -> T {
diff --git a/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir b/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir
index 26068931aaf..9eb0e09bf1b 100644
--- a/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir
+++ b/tests/mir-opt/dest-prop/dead_stores_better.f.DestinationPropagation.after.mir
@@ -21,7 +21,7 @@ fn f(_1: usize) -> usize {
         nop;                             // scope 1 at $DIR/dead_stores_better.rs:+4:8: +4:9
         _0 = id::<usize>(move _1) -> bb1; // scope 1 at $DIR/dead_stores_better.rs:+4:5: +4:10
                                          // mir::Constant
-                                         // + span: $DIR/dead_stores_better.rs:16:5: 16:7
+                                         // + span: $DIR/dead_stores_better.rs:17:5: 17:7
                                          // + literal: Const { ty: fn(usize) -> usize {id::<usize>}, val: Value(<ZST>) }
     }
 
diff --git a/tests/mir-opt/dest-prop/dead_stores_better.rs b/tests/mir-opt/dest-prop/dead_stores_better.rs
index 003ad57d83e..72d406bfd40 100644
--- a/tests/mir-opt/dest-prop/dead_stores_better.rs
+++ b/tests/mir-opt/dest-prop/dead_stores_better.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // This is a copy of the `dead_stores_79191` test, except that we turn on DSE. This demonstrates
 // that that pass enables this one to do more optimizations.
 
diff --git a/tests/mir-opt/dest-prop/simple.rs b/tests/mir-opt/dest-prop/simple.rs
index d4c27228fe4..3a4aec34e8c 100644
--- a/tests/mir-opt/dest-prop/simple.rs
+++ b/tests/mir-opt/dest-prop/simple.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 //! Copy of `nrvo-simple.rs`, to ensure that full dest-prop handles it too.
 // unit-test: DestinationPropagation
 // EMIT_MIR simple.nrvo.DestinationPropagation.diff
diff --git a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.diff b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.diff
index fbed3178801..457fc830874 100644
--- a/tests/mir-opt/dest-prop/union.main.DestinationPropagation.diff
+++ b/tests/mir-opt/dest-prop/union.main.DestinationPropagation.diff
@@ -10,7 +10,7 @@
           debug un => _1;                  // in scope 1 at $DIR/union.rs:+5:9: +5:11
           scope 2 {
           }
-          scope 3 (inlined std::mem::drop::<u32>) { // at $DIR/union.rs:15:5: 15:27
+          scope 3 (inlined std::mem::drop::<u32>) { // at $DIR/union.rs:16:5: 16:27
               debug _x => _3;              // in scope 3 at $SRC_DIR/core/src/mem/mod.rs:LL:COL
           }
       }
@@ -20,7 +20,7 @@
           StorageLive(_2);                 // scope 0 at $DIR/union.rs:+5:23: +5:28
           _2 = val() -> bb1;               // scope 0 at $DIR/union.rs:+5:23: +5:28
                                            // mir::Constant
-                                           // + span: $DIR/union.rs:13:23: 13:26
+                                           // + span: $DIR/union.rs:14:23: 14:26
                                            // + literal: Const { ty: fn() -> u32 {val}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/dest-prop/union.rs b/tests/mir-opt/dest-prop/union.rs
index eb6cb09fc45..062d02d0673 100644
--- a/tests/mir-opt/dest-prop/union.rs
+++ b/tests/mir-opt/dest-prop/union.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 //! Tests that we can propagate into places that are projections into unions
 // compile-flags: -Zunsound-mir-opts
 fn val() -> u32 {
diff --git a/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.diff b/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.diff
index 9ea756c2712..ae63d724d0a 100644
--- a/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.diff
+++ b/tests/mir-opt/dest-prop/unreachable.f.DestinationPropagation.diff
@@ -36,7 +36,7 @@
 -         _6 = _2;                         // scope 1 at $DIR/unreachable.rs:+3:14: +3:15
 -         _4 = g::<T>(move _5, move _6) -> bb2; // scope 1 at $DIR/unreachable.rs:+3:9: +3:16
 -                                          // mir::Constant
--                                          // + span: $DIR/unreachable.rs:11:9: 11:10
+-                                          // + span: $DIR/unreachable.rs:12:9: 12:10
 -                                          // + literal: Const { ty: fn(T, T) {g::<T>}, val: Value(<ZST>) }
 -     }
 - 
@@ -60,7 +60,7 @@
 +         _9 = _1;                         // scope 1 at $DIR/unreachable.rs:+5:14: +5:15
 +         _7 = g::<T>(move _1, move _9) -> bb2; // scope 1 at $DIR/unreachable.rs:+5:9: +5:16
                                            // mir::Constant
-                                           // + span: $DIR/unreachable.rs:13:9: 13:10
+                                           // + span: $DIR/unreachable.rs:14:9: 14:10
                                            // + literal: Const { ty: fn(T, T) {g::<T>}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/dest-prop/unreachable.rs b/tests/mir-opt/dest-prop/unreachable.rs
index 32b5def984a..c73d11ae3ba 100644
--- a/tests/mir-opt/dest-prop/unreachable.rs
+++ b/tests/mir-opt/dest-prop/unreachable.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Check that unreachable code is removed after the destination propagation.
 // Regression test for issue #105428.
 //
diff --git a/tests/mir-opt/div_overflow.rs b/tests/mir-opt/div_overflow.rs
index 10ce5bc0f4f..fe34a865b93 100644
--- a/tests/mir-opt/div_overflow.rs
+++ b/tests/mir-opt/div_overflow.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // compile-flags: -Copt-level=0 -Coverflow-checks=yes
 
 // Tests that division with a const does not emit a panicking branch for overflow
diff --git a/tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff b/tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff
index c1a42a47ed2..c0fc1fb1df3 100644
--- a/tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff
+++ b/tests/mir-opt/dont_yeet_assert.generic.InstCombine.diff
@@ -7,7 +7,7 @@
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/dont_yeet_assert.rs:+1:5: +1:61
-          _1 = assert_mem_uninitialized_valid::<&T>() -> bb1; // scope 0 at $DIR/dont_yeet_assert.rs:+1:5: +1:61
+          _1 = assert_mem_uninitialized_valid::<&T>() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/dont_yeet_assert.rs:+1:5: +1:61
                                            // mir::Constant
                                            // + span: $DIR/dont_yeet_assert.rs:10:5: 10:59
                                            // + user_ty: UserType(0)
diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
index ec063294856..8a4a1682519 100644
--- a/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
+++ b/tests/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
@@ -40,7 +40,7 @@
           _5 = &(*_1);                     // scope 0 at $DIR/funky_arms.rs:+4:22: +4:37
           _4 = Formatter::<'_>::sign_plus(move _5) -> bb1; // scope 0 at $DIR/funky_arms.rs:+4:22: +4:37
                                            // mir::Constant
-                                           // + span: $DIR/funky_arms.rs:15:26: 15:35
+                                           // + span: $DIR/funky_arms.rs:16:26: 16:35
                                            // + literal: Const { ty: for<'a> fn(&'a Formatter<'_>) -> bool {Formatter::<'_>::sign_plus}, val: Value(<ZST>) }
       }
   
@@ -74,7 +74,7 @@
           _8 = &(*_1);                     // scope 3 at $DIR/funky_arms.rs:+13:30: +13:45
           _7 = Formatter::<'_>::precision(move _8) -> bb5; // scope 3 at $DIR/funky_arms.rs:+13:30: +13:45
                                            // mir::Constant
-                                           // + span: $DIR/funky_arms.rs:24:34: 24:43
+                                           // + span: $DIR/funky_arms.rs:25:34: 25:43
                                            // + literal: Const { ty: for<'a> fn(&'a Formatter<'_>) -> Option<usize> {Formatter::<'_>::precision}, val: Value(<ZST>) }
       }
   
@@ -95,7 +95,7 @@
           StorageDead(_15);                // scope 3 at $DIR/funky_arms.rs:+15:78: +15:79
           _0 = float_to_exponential_common_exact::<T>(_1, _2, move _13, move _14, _3) -> bb7; // scope 3 at $DIR/funky_arms.rs:+15:9: +15:87
                                            // mir::Constant
-                                           // + span: $DIR/funky_arms.rs:26:9: 26:42
+                                           // + span: $DIR/funky_arms.rs:27:9: 27:42
                                            // + literal: Const { ty: for<'a, 'b, 'c> fn(&'a mut Formatter<'b>, &'c T, Sign, u32, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_exact::<T>}, val: Value(<ZST>) }
       }
   
@@ -110,7 +110,7 @@
           _20 = _6;                        // scope 2 at $DIR/funky_arms.rs:+17:56: +17:60
           _0 = float_to_exponential_common_shortest::<T>(_1, _2, move _20, _3) -> bb9; // scope 2 at $DIR/funky_arms.rs:+17:9: +17:68
                                            // mir::Constant
-                                           // + span: $DIR/funky_arms.rs:28:9: 28:45
+                                           // + span: $DIR/funky_arms.rs:29:9: 29:45
                                            // + literal: Const { ty: for<'a, 'b, 'c> fn(&'a mut Formatter<'b>, &'c T, Sign, bool) -> Result<(), std::fmt::Error> {float_to_exponential_common_shortest::<T>}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/funky_arms.rs b/tests/mir-opt/funky_arms.rs
index 3e70d85e0d4..c4f75b5df6d 100644
--- a/tests/mir-opt/funky_arms.rs
+++ b/tests/mir-opt/funky_arms.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // compile-flags: --crate-type lib -Cdebug-assertions=no
 
 #![feature(flt2dec)]
diff --git a/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir b/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir
index cfbe0aaf252..32b472ebeeb 100644
--- a/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir
+++ b/tests/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir
@@ -110,7 +110,7 @@ yields ()
 
     bb13 (cleanup): {
         StorageDead(_3);                 // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6
-        drop(_1) -> bb14;                // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6
+        drop(_1) -> [return: bb14, unwind terminate]; // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6
     }
 
     bb14 (cleanup): {
@@ -119,6 +119,6 @@ yields ()
 
     bb15 (cleanup): {
         StorageDead(_3);                 // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6
-        drop(_1) -> bb14;                // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6
+        drop(_1) -> [return: bb14, unwind terminate]; // scope 0 at $DIR/generator_storage_dead_unwind.rs:+6:5: +6:6
     }
 }
diff --git a/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir b/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir
index 7efda05d2b8..dc9bb533f13 100644
--- a/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir
+++ b/tests/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir
@@ -63,7 +63,7 @@ fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator_tiny.rs:19:16: 19:24
         StorageDead(_7);                 // scope 1 at $DIR/generator_tiny.rs:+3:17: +3:18
         StorageDead(_6);                 // scope 1 at $DIR/generator_tiny.rs:+3:18: +3:19
         StorageLive(_8);                 // scope 1 at $DIR/generator_tiny.rs:+4:13: +4:21
-        _8 = callee() -> bb4;            // scope 1 at $DIR/generator_tiny.rs:+4:13: +4:21
+        _8 = callee() -> [return: bb4, unwind unreachable]; // scope 1 at $DIR/generator_tiny.rs:+4:13: +4:21
                                          // mir::Constant
                                          // + span: $DIR/generator_tiny.rs:23:13: 23:19
                                          // + literal: Const { ty: fn() {callee}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/inline/asm_unwind.main.Inline.diff b/tests/mir-opt/inline/asm_unwind.main.Inline.diff
index ed290063a93..ba1bfec05d2 100644
--- a/tests/mir-opt/inline/asm_unwind.main.Inline.diff
+++ b/tests/mir-opt/inline/asm_unwind.main.Inline.diff
@@ -35,7 +35,7 @@
 +     }
 + 
 +     bb3 (cleanup): {
-+         drop(_2) -> bb4;                 // scope 1 at $DIR/asm_unwind.rs:17:1: 17:2
++         drop(_2) -> [return: bb4, unwind terminate]; // scope 1 at $DIR/asm_unwind.rs:17:1: 17:2
 +     }
 + 
 +     bb4 (cleanup): {
diff --git a/tests/mir-opt/inline/cycle.f.Inline.diff b/tests/mir-opt/inline/cycle.f.Inline.diff
index 501390c3bf1..8da59757743 100644
--- a/tests/mir-opt/inline/cycle.f.Inline.diff
+++ b/tests/mir-opt/inline/cycle.f.Inline.diff
@@ -33,7 +33,7 @@
       }
   
       bb3 (cleanup): {
-          drop(_1) -> bb4;                 // scope 0 at $DIR/cycle.rs:+2:1: +2:2
+          drop(_1) -> [return: bb4, unwind terminate]; // scope 0 at $DIR/cycle.rs:+2:1: +2:2
       }
   
       bb4 (cleanup): {
diff --git a/tests/mir-opt/inline/cycle.g.Inline.diff b/tests/mir-opt/inline/cycle.g.Inline.diff
index 20d313aecf5..1e6e30f9e9b 100644
--- a/tests/mir-opt/inline/cycle.g.Inline.diff
+++ b/tests/mir-opt/inline/cycle.g.Inline.diff
@@ -42,7 +42,7 @@
 +     }
 + 
 +     bb2 (cleanup): {
-+         drop(_2) -> bb3;                 // scope 1 at $DIR/cycle.rs:7:1: 7:2
++         drop(_2) -> [return: bb3, unwind terminate]; // scope 1 at $DIR/cycle.rs:7:1: 7:2
 +     }
 + 
 +     bb3 (cleanup): {
diff --git a/tests/mir-opt/inline/cycle.main.Inline.diff b/tests/mir-opt/inline/cycle.main.Inline.diff
index dacc5f4be9d..315634945e4 100644
--- a/tests/mir-opt/inline/cycle.main.Inline.diff
+++ b/tests/mir-opt/inline/cycle.main.Inline.diff
@@ -42,7 +42,7 @@
 +     }
 + 
 +     bb2 (cleanup): {
-+         drop(_2) -> bb3;                 // scope 1 at $DIR/cycle.rs:7:1: 7:2
++         drop(_2) -> [return: bb3, unwind terminate]; // scope 1 at $DIR/cycle.rs:7:1: 7:2
 +     }
 + 
 +     bb3 (cleanup): {
diff --git a/tests/mir-opt/inline/dyn_trait.get_query.Inline.diff b/tests/mir-opt/inline/dyn_trait.get_query.Inline.diff
index 64c3e47ff46..75d9bd54d5b 100644
--- a/tests/mir-opt/inline/dyn_trait.get_query.Inline.diff
+++ b/tests/mir-opt/inline/dyn_trait.get_query.Inline.diff
@@ -9,11 +9,11 @@
       let mut _4: &<Q as Query>::C;        // in scope 0 at $DIR/dyn_trait.rs:+2:23: +2:24
       scope 1 {
           debug c => _2;                   // in scope 1 at $DIR/dyn_trait.rs:+1:9: +1:10
-+         scope 2 (inlined try_execute_query::<<Q as Query>::C>) { // at $DIR/dyn_trait.rs:34:5: 34:25
-+             debug c => _4;               // in scope 2 at $DIR/dyn_trait.rs:26:36: 26:37
-+             let mut _5: &dyn Cache<V = <Q as Query>::V>; // in scope 2 at $DIR/dyn_trait.rs:27:14: 27:15
-+             scope 3 (inlined mk_cycle::<<Q as Query>::V>) { // at $DIR/dyn_trait.rs:27:5: 27:16
-+                 debug c => _5;           // in scope 3 at $DIR/dyn_trait.rs:20:27: 20:28
++         scope 2 (inlined try_execute_query::<<Q as Query>::C>) { // at $DIR/dyn_trait.rs:35:5: 35:25
++             debug c => _4;               // in scope 2 at $DIR/dyn_trait.rs:27:36: 27:37
++             let mut _5: &dyn Cache<V = <Q as Query>::V>; // in scope 2 at $DIR/dyn_trait.rs:28:14: 28:15
++             scope 3 (inlined mk_cycle::<<Q as Query>::V>) { // at $DIR/dyn_trait.rs:28:5: 28:16
++                 debug c => _5;           // in scope 3 at $DIR/dyn_trait.rs:21:27: 21:28
 +             }
 +         }
       }
@@ -24,7 +24,7 @@
           _3 = &(*_1);                     // scope 0 at $DIR/dyn_trait.rs:+1:22: +1:23
           _2 = <Q as Query>::cache::<T>(move _3) -> bb1; // scope 0 at $DIR/dyn_trait.rs:+1:13: +1:24
                                            // mir::Constant
-                                           // + span: $DIR/dyn_trait.rs:33:13: 33:21
+                                           // + span: $DIR/dyn_trait.rs:34:13: 34:21
                                            // + user_ty: UserType(0)
                                            // + literal: Const { ty: for<'a> fn(&'a T) -> &'a <Q as Query>::C {<Q as Query>::cache::<T>}, val: Value(<ZST>) }
       }
@@ -34,18 +34,18 @@
           StorageLive(_4);                 // scope 1 at $DIR/dyn_trait.rs:+2:23: +2:24
           _4 = &(*_2);                     // scope 1 at $DIR/dyn_trait.rs:+2:23: +2:24
 -         _0 = try_execute_query::<<Q as Query>::C>(move _4) -> bb2; // scope 1 at $DIR/dyn_trait.rs:+2:5: +2:25
-+         StorageLive(_5);                 // scope 2 at $DIR/dyn_trait.rs:27:14: 27:15
-+         _5 = _4 as &dyn Cache<V = <Q as Query>::V> (Pointer(Unsize)); // scope 2 at $DIR/dyn_trait.rs:27:14: 27:15
-+         _0 = <dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache(_5) -> bb2; // scope 3 at $DIR/dyn_trait.rs:21:5: 21:22
++         StorageLive(_5);                 // scope 2 at $DIR/dyn_trait.rs:28:14: 28:15
++         _5 = _4 as &dyn Cache<V = <Q as Query>::V> (Pointer(Unsize)); // scope 2 at $DIR/dyn_trait.rs:28:14: 28:15
++         _0 = <dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache(_5) -> bb2; // scope 3 at $DIR/dyn_trait.rs:22:5: 22:22
                                            // mir::Constant
--                                          // + span: $DIR/dyn_trait.rs:34:5: 34:22
+-                                          // + span: $DIR/dyn_trait.rs:35:5: 35:22
 -                                          // + literal: Const { ty: for<'a> fn(&'a <Q as Query>::C) {try_execute_query::<<Q as Query>::C>}, val: Value(<ZST>) }
-+                                          // + span: $DIR/dyn_trait.rs:21:7: 21:20
++                                          // + span: $DIR/dyn_trait.rs:22:7: 22:20
 +                                          // + literal: Const { ty: for<'a> fn(&'a dyn Cache<V = <Q as Query>::V>) {<dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache}, val: Value(<ZST>) }
       }
   
       bb2: {
-+         StorageDead(_5);                 // scope 2 at $DIR/dyn_trait.rs:27:15: 27:16
++         StorageDead(_5);                 // scope 2 at $DIR/dyn_trait.rs:28:15: 28:16
           StorageDead(_4);                 // scope 1 at $DIR/dyn_trait.rs:+2:24: +2:25
           StorageDead(_2);                 // scope 0 at $DIR/dyn_trait.rs:+3:1: +3:2
           return;                          // scope 0 at $DIR/dyn_trait.rs:+3:2: +3:2
diff --git a/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff
index 7653a5ded44..925c95988b7 100644
--- a/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff
+++ b/tests/mir-opt/inline/dyn_trait.mk_cycle.Inline.diff
@@ -11,7 +11,7 @@
           _2 = &(*_1);                     // scope 0 at $DIR/dyn_trait.rs:+1:5: +1:22
           _0 = <dyn Cache<V = V> as Cache>::store_nocache(move _2) -> bb1; // scope 0 at $DIR/dyn_trait.rs:+1:5: +1:22
                                            // mir::Constant
-                                           // + span: $DIR/dyn_trait.rs:21:7: 21:20
+                                           // + span: $DIR/dyn_trait.rs:22:7: 22:20
                                            // + literal: Const { ty: for<'a> fn(&'a dyn Cache<V = V>) {<dyn Cache<V = V> as Cache>::store_nocache}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/inline/dyn_trait.rs b/tests/mir-opt/inline/dyn_trait.rs
index 6a46e1e07b1..2af81f82570 100644
--- a/tests/mir-opt/inline/dyn_trait.rs
+++ b/tests/mir-opt/inline/dyn_trait.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 #![crate_type = "lib"]
 
 use std::fmt::Debug;
diff --git a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff
index 3fa9c3e88f6..f4e5272abfc 100644
--- a/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff
+++ b/tests/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff
@@ -6,8 +6,8 @@
       let mut _0: ();                      // return place in scope 0 at $DIR/dyn_trait.rs:+0:43: +0:43
       let mut _2: &dyn Cache<V = <C as Cache>::V>; // in scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15
       let mut _3: &C;                      // in scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15
-+     scope 1 (inlined mk_cycle::<<C as Cache>::V>) { // at $DIR/dyn_trait.rs:27:5: 27:16
-+         debug c => _2;                   // in scope 1 at $DIR/dyn_trait.rs:20:27: 20:28
++     scope 1 (inlined mk_cycle::<<C as Cache>::V>) { // at $DIR/dyn_trait.rs:28:5: 28:16
++         debug c => _2;                   // in scope 1 at $DIR/dyn_trait.rs:21:27: 21:28
 +     }
   
       bb0: {
@@ -17,11 +17,11 @@
           _2 = move _3 as &dyn Cache<V = <C as Cache>::V> (Pointer(Unsize)); // scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15
           StorageDead(_3);                 // scope 0 at $DIR/dyn_trait.rs:+1:14: +1:15
 -         _0 = mk_cycle::<<C as Cache>::V>(move _2) -> bb1; // scope 0 at $DIR/dyn_trait.rs:+1:5: +1:16
-+         _0 = <dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache(_2) -> bb1; // scope 1 at $DIR/dyn_trait.rs:21:5: 21:22
++         _0 = <dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache(_2) -> bb1; // scope 1 at $DIR/dyn_trait.rs:22:5: 22:22
                                            // mir::Constant
--                                          // + span: $DIR/dyn_trait.rs:27:5: 27:13
+-                                          // + span: $DIR/dyn_trait.rs:28:5: 28:13
 -                                          // + literal: Const { ty: for<'a> fn(&'a (dyn Cache<V = <C as Cache>::V> + 'a)) {mk_cycle::<<C as Cache>::V>}, val: Value(<ZST>) }
-+                                          // + span: $DIR/dyn_trait.rs:21:7: 21:20
++                                          // + span: $DIR/dyn_trait.rs:22:7: 22:20
 +                                          // + literal: Const { ty: for<'a> fn(&'a dyn Cache<V = <C as Cache>::V>) {<dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/inline/exponential_runtime.main.Inline.diff b/tests/mir-opt/inline/exponential_runtime.main.Inline.diff
index dd1f253cb47..30af8661dec 100644
--- a/tests/mir-opt/inline/exponential_runtime.main.Inline.diff
+++ b/tests/mir-opt/inline/exponential_runtime.main.Inline.diff
@@ -4,14 +4,14 @@
   fn main() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/exponential_runtime.rs:+0:11: +0:11
       let _1: ();                          // in scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22
-+     scope 1 (inlined <() as G>::call) {  // at $DIR/exponential_runtime.rs:86:5: 86:22
-+         let _2: ();                      // in scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25
-+         let _3: ();                      // in scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
-+         let _4: ();                      // in scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25
-+         scope 2 (inlined <() as F>::call) { // at $DIR/exponential_runtime.rs:73:9: 73:25
-+             let _5: ();                  // in scope 2 at $DIR/exponential_runtime.rs:61:9: 61:25
-+             let _6: ();                  // in scope 2 at $DIR/exponential_runtime.rs:62:9: 62:25
-+             let _7: ();                  // in scope 2 at $DIR/exponential_runtime.rs:63:9: 63:25
++     scope 1 (inlined <() as G>::call) {  // at $DIR/exponential_runtime.rs:87:5: 87:22
++         let _2: ();                      // in scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
++         let _3: ();                      // in scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25
++         let _4: ();                      // in scope 1 at $DIR/exponential_runtime.rs:76:9: 76:25
++         scope 2 (inlined <() as F>::call) { // at $DIR/exponential_runtime.rs:74:9: 74:25
++             let _5: ();                  // in scope 2 at $DIR/exponential_runtime.rs:62:9: 62:25
++             let _6: ();                  // in scope 2 at $DIR/exponential_runtime.rs:63:9: 63:25
++             let _7: ();                  // in scope 2 at $DIR/exponential_runtime.rs:64:9: 64:25
 +         }
 +     }
   
@@ -21,14 +21,14 @@
 +         StorageLive(_2);                 // scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22
 +         StorageLive(_3);                 // scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22
 +         StorageLive(_4);                 // scope 0 at $DIR/exponential_runtime.rs:+1:5: +1:22
-+         StorageLive(_5);                 // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25
-+         StorageLive(_6);                 // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25
-+         StorageLive(_7);                 // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25
-+         _5 = <() as E>::call() -> bb4;   // scope 2 at $DIR/exponential_runtime.rs:61:9: 61:25
++         StorageLive(_5);                 // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
++         StorageLive(_6);                 // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
++         StorageLive(_7);                 // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
++         _5 = <() as E>::call() -> bb4;   // scope 2 at $DIR/exponential_runtime.rs:62:9: 62:25
                                            // mir::Constant
--                                          // + span: $DIR/exponential_runtime.rs:86:5: 86:20
+-                                          // + span: $DIR/exponential_runtime.rs:87:5: 87:20
 -                                          // + literal: Const { ty: fn() {<() as G>::call}, val: Value(<ZST>) }
-+                                          // + span: $DIR/exponential_runtime.rs:61:9: 61:23
++                                          // + span: $DIR/exponential_runtime.rs:62:9: 62:23
 +                                          // + literal: Const { ty: fn() {<() as E>::call}, val: Value(<ZST>) }
       }
   
@@ -42,33 +42,33 @@
 +     }
 + 
 +     bb2: {
-+         StorageDead(_7);                 // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25
-+         StorageDead(_6);                 // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25
-+         StorageDead(_5);                 // scope 1 at $DIR/exponential_runtime.rs:73:9: 73:25
-+         _3 = <() as F>::call() -> bb3;   // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
++         StorageDead(_7);                 // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
++         StorageDead(_6);                 // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
++         StorageDead(_5);                 // scope 1 at $DIR/exponential_runtime.rs:74:9: 74:25
++         _3 = <() as F>::call() -> bb3;   // scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25
 +                                          // mir::Constant
-+                                          // + span: $DIR/exponential_runtime.rs:74:9: 74:23
++                                          // + span: $DIR/exponential_runtime.rs:75:9: 75:23
 +                                          // + literal: Const { ty: fn() {<() as F>::call}, val: Value(<ZST>) }
 +     }
 + 
 +     bb3: {
-+         _4 = <() as F>::call() -> bb1;   // scope 1 at $DIR/exponential_runtime.rs:75:9: 75:25
++         _4 = <() as F>::call() -> bb1;   // scope 1 at $DIR/exponential_runtime.rs:76:9: 76:25
 +                                          // mir::Constant
-+                                          // + span: $DIR/exponential_runtime.rs:75:9: 75:23
++                                          // + span: $DIR/exponential_runtime.rs:76:9: 76:23
 +                                          // + literal: Const { ty: fn() {<() as F>::call}, val: Value(<ZST>) }
 +     }
 + 
 +     bb4: {
-+         _6 = <() as E>::call() -> bb5;   // scope 2 at $DIR/exponential_runtime.rs:62:9: 62:25
++         _6 = <() as E>::call() -> bb5;   // scope 2 at $DIR/exponential_runtime.rs:63:9: 63:25
 +                                          // mir::Constant
-+                                          // + span: $DIR/exponential_runtime.rs:62:9: 62:23
++                                          // + span: $DIR/exponential_runtime.rs:63:9: 63:23
 +                                          // + literal: Const { ty: fn() {<() as E>::call}, val: Value(<ZST>) }
 +     }
 + 
 +     bb5: {
-+         _7 = <() as E>::call() -> bb2;   // scope 2 at $DIR/exponential_runtime.rs:63:9: 63:25
++         _7 = <() as E>::call() -> bb2;   // scope 2 at $DIR/exponential_runtime.rs:64:9: 64:25
 +                                          // mir::Constant
-+                                          // + span: $DIR/exponential_runtime.rs:63:9: 63:23
++                                          // + span: $DIR/exponential_runtime.rs:64:9: 64:23
 +                                          // + literal: Const { ty: fn() {<() as E>::call}, val: Value(<ZST>) }
       }
   }
diff --git a/tests/mir-opt/inline/exponential_runtime.rs b/tests/mir-opt/inline/exponential_runtime.rs
index d9219d76a98..39985528f46 100644
--- a/tests/mir-opt/inline/exponential_runtime.rs
+++ b/tests/mir-opt/inline/exponential_runtime.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Checks that code with exponential runtime does not have exponential behavior in inlining.
 
 trait A {
diff --git a/tests/mir-opt/inline/inline_cycle.one.Inline.diff b/tests/mir-opt/inline/inline_cycle.one.Inline.diff
index 5510cd7bc8c..f6ba69a1d29 100644
--- a/tests/mir-opt/inline/inline_cycle.one.Inline.diff
+++ b/tests/mir-opt/inline/inline_cycle.one.Inline.diff
@@ -4,9 +4,9 @@
   fn one() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/inline_cycle.rs:+0:10: +0:10
       let _1: ();                          // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24
-+     scope 1 (inlined <C as Call>::call) { // at $DIR/inline_cycle.rs:14:5: 14:24
-+         scope 2 (inlined <A<C> as Call>::call) { // at $DIR/inline_cycle.rs:43:9: 43:23
-+             scope 3 (inlined <B<C> as Call>::call) { // at $DIR/inline_cycle.rs:28:9: 28:31
++     scope 1 (inlined <C as Call>::call) { // at $DIR/inline_cycle.rs:15:5: 15:24
++         scope 2 (inlined <A<C> as Call>::call) { // at $DIR/inline_cycle.rs:44:9: 44:23
++             scope 3 (inlined <B<C> as Call>::call) { // at $DIR/inline_cycle.rs:29:9: 29:31
 +             }
 +         }
 +     }
@@ -14,10 +14,10 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24
 -         _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:24
-+         _1 = <C as Call>::call() -> bb1; // scope 3 at $DIR/inline_cycle.rs:36:9: 36:28
++         _1 = <C as Call>::call() -> bb1; // scope 3 at $DIR/inline_cycle.rs:37:9: 37:28
                                            // mir::Constant
--                                          // + span: $DIR/inline_cycle.rs:14:5: 14:22
-+                                          // + span: $DIR/inline_cycle.rs:36:9: 36:26
+-                                          // + span: $DIR/inline_cycle.rs:15:5: 15:22
++                                          // + span: $DIR/inline_cycle.rs:37:9: 37:26
                                            // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/inline/inline_cycle.rs b/tests/mir-opt/inline/inline_cycle.rs
index 63ad57de1d4..2f81696cf03 100644
--- a/tests/mir-opt/inline/inline_cycle.rs
+++ b/tests/mir-opt/inline/inline_cycle.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Check that inliner handles various forms of recursion and doesn't fall into
 // an infinite inlining cycle. The particular outcome of inlining is not
 // crucial otherwise.
diff --git a/tests/mir-opt/inline/inline_cycle.two.Inline.diff b/tests/mir-opt/inline/inline_cycle.two.Inline.diff
index 0215b3d93f9..c8f58111da7 100644
--- a/tests/mir-opt/inline/inline_cycle.two.Inline.diff
+++ b/tests/mir-opt/inline/inline_cycle.two.Inline.diff
@@ -5,11 +5,11 @@
       let mut _0: ();                      // return place in scope 0 at $DIR/inline_cycle.rs:+0:10: +0:10
       let _1: ();                          // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12
 +     let mut _2: fn() {f};                // in scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12
-+     let mut _4: ();                      // in scope 0 at $DIR/inline_cycle.rs:54:5: 54:8
-+     scope 1 (inlined call::<fn() {f}>) { // at $DIR/inline_cycle.rs:49:5: 49:12
-+         debug f => _2;                   // in scope 1 at $DIR/inline_cycle.rs:53:22: 53:23
-+         let _3: ();                      // in scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
-+         scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) { // at $DIR/inline_cycle.rs:54:5: 54:8
++     let mut _4: ();                      // in scope 0 at $DIR/inline_cycle.rs:55:5: 55:8
++     scope 1 (inlined call::<fn() {f}>) { // at $DIR/inline_cycle.rs:50:5: 50:12
++         debug f => _2;                   // in scope 1 at $DIR/inline_cycle.rs:54:22: 54:23
++         let _3: ();                      // in scope 1 at $DIR/inline_cycle.rs:55:5: 55:8
++         scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) { // at $DIR/inline_cycle.rs:55:5: 55:8
 +         }
 +     }
   
@@ -19,19 +19,19 @@
 +         StorageLive(_2);                 // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12
 +         _2 = f;                          // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12
                                            // mir::Constant
--                                          // + span: $DIR/inline_cycle.rs:49:5: 49:9
+-                                          // + span: $DIR/inline_cycle.rs:50:5: 50:9
 -                                          // + literal: Const { ty: fn(fn() {f}) {call::<fn() {f}>}, val: Value(<ZST>) }
 -                                          // mir::Constant
-                                           // + span: $DIR/inline_cycle.rs:49:10: 49:11
+                                           // + span: $DIR/inline_cycle.rs:50:10: 50:11
                                            // + literal: Const { ty: fn() {f}, val: Value(<ZST>) }
 +         StorageLive(_3);                 // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12
-+         StorageLive(_4);                 // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
-+         _4 = const ();                   // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
++         StorageLive(_4);                 // scope 1 at $DIR/inline_cycle.rs:55:5: 55:8
++         _4 = const ();                   // scope 1 at $DIR/inline_cycle.rs:55:5: 55:8
 +         _3 = move _2() -> bb1;           // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL
       }
   
       bb1: {
-+         StorageDead(_4);                 // scope 1 at $DIR/inline_cycle.rs:54:5: 54:8
++         StorageDead(_4);                 // scope 1 at $DIR/inline_cycle.rs:55:5: 55:8
 +         StorageDead(_3);                 // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12
 +         StorageDead(_2);                 // scope 0 at $DIR/inline_cycle.rs:+1:5: +1:12
           StorageDead(_1);                 // scope 0 at $DIR/inline_cycle.rs:+1:12: +1:13
diff --git a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.diff b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.diff
index 04de3e61e5f..9429ca59364 100644
--- a/tests/mir-opt/inline/inline_cycle_generic.main.Inline.diff
+++ b/tests/mir-opt/inline/inline_cycle_generic.main.Inline.diff
@@ -4,19 +4,19 @@
   fn main() -> () {
       let mut _0: ();                      // return place in scope 0 at $DIR/inline_cycle_generic.rs:+0:11: +0:11
       let _1: ();                          // in scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24
-+     scope 1 (inlined <C as Call>::call) { // at $DIR/inline_cycle_generic.rs:9:5: 9:24
-+         scope 2 (inlined <B<A> as Call>::call) { // at $DIR/inline_cycle_generic.rs:38:9: 38:31
++     scope 1 (inlined <C as Call>::call) { // at $DIR/inline_cycle_generic.rs:10:5: 10:24
++         scope 2 (inlined <B<A> as Call>::call) { // at $DIR/inline_cycle_generic.rs:39:9: 39:31
 +         }
 +     }
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24
 -         _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline_cycle_generic.rs:+1:5: +1:24
-+         _1 = <A as Call>::call() -> bb1; // scope 2 at $DIR/inline_cycle_generic.rs:31:9: 31:28
++         _1 = <A as Call>::call() -> bb1; // scope 2 at $DIR/inline_cycle_generic.rs:32:9: 32:28
                                            // mir::Constant
--                                          // + span: $DIR/inline_cycle_generic.rs:9:5: 9:22
+-                                          // + span: $DIR/inline_cycle_generic.rs:10:5: 10:22
 -                                          // + literal: Const { ty: fn() {<C as Call>::call}, val: Value(<ZST>) }
-+                                          // + span: $DIR/inline_cycle_generic.rs:31:9: 31:26
++                                          // + span: $DIR/inline_cycle_generic.rs:32:9: 32:26
 +                                          // + literal: Const { ty: fn() {<A as Call>::call}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/inline/inline_cycle_generic.rs b/tests/mir-opt/inline/inline_cycle_generic.rs
index 24b4f37939a..84e6e4005a6 100644
--- a/tests/mir-opt/inline/inline_cycle_generic.rs
+++ b/tests/mir-opt/inline/inline_cycle_generic.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Check that inliner handles various forms of recursion and doesn't fall into
 // an infinite inlining cycle. The particular outcome of inlining is not
 // crucial otherwise.
diff --git a/tests/mir-opt/inline/inline_diverging.h.Inline.diff b/tests/mir-opt/inline/inline_diverging.h.Inline.diff
index 31208e0052c..d501b6ca8d2 100644
--- a/tests/mir-opt/inline/inline_diverging.h.Inline.diff
+++ b/tests/mir-opt/inline/inline_diverging.h.Inline.diff
@@ -58,11 +58,11 @@
 +     }
 + 
 +     bb3 (cleanup): {
-+         drop(_3) -> bb4;                 // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
++         drop(_3) -> [return: bb4, unwind terminate]; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
 +     }
 + 
 +     bb4 (cleanup): {
-+         drop(_2) -> bb5;                 // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
++         drop(_2) -> [return: bb5, unwind terminate]; // scope 1 at $DIR/inline_diverging.rs:30:1: 30:2
 +     }
 + 
 +     bb5 (cleanup): {
diff --git a/tests/mir-opt/inline/inline_instruction_set.default.Inline.diff b/tests/mir-opt/inline/inline_instruction_set.default.Inline.diff
index f1988ea4bd6..a1d2423ae27 100644
--- a/tests/mir-opt/inline/inline_instruction_set.default.Inline.diff
+++ b/tests/mir-opt/inline/inline_instruction_set.default.Inline.diff
@@ -16,7 +16,7 @@
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
-          _1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
+          _1 = instruction_set_a32() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
                                            // mir::Constant
                                            // + span: $DIR/inline_instruction_set.rs:57:5: 57:24
                                            // + literal: Const { ty: fn() {instruction_set_a32}, val: Value(<ZST>) }
@@ -25,7 +25,7 @@
       bb1: {
           StorageDead(_1);                 // scope 0 at $DIR/inline_instruction_set.rs:+1:26: +1:27
           StorageLive(_2);                 // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
-          _2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
+          _2 = instruction_set_t32() -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
                                            // mir::Constant
                                            // + span: $DIR/inline_instruction_set.rs:58:5: 58:24
                                            // + literal: Const { ty: fn() {instruction_set_t32}, val: Value(<ZST>) }
@@ -34,7 +34,7 @@
       bb2: {
           StorageDead(_2);                 // scope 0 at $DIR/inline_instruction_set.rs:+2:26: +2:27
           StorageLive(_3);                 // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
--         _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
+-         _3 = instruction_set_default() -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
 -                                          // mir::Constant
 -                                          // + span: $DIR/inline_instruction_set.rs:59:5: 59:28
 -                                          // + literal: Const { ty: fn() {instruction_set_default}, val: Value(<ZST>) }
@@ -43,11 +43,11 @@
 -     bb3: {
           StorageDead(_3);                 // scope 0 at $DIR/inline_instruction_set.rs:+3:30: +3:31
           StorageLive(_4);                 // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
--         _4 = inline_always_and_using_inline_asm() -> bb4; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
+-         _4 = inline_always_and_using_inline_asm() -> [return: bb4, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
 -                                          // mir::Constant
 -                                          // + span: $DIR/inline_instruction_set.rs:60:5: 60:39
 -                                          // + literal: Const { ty: fn() {inline_always_and_using_inline_asm}, val: Value(<ZST>) }
-+         asm!("/* do nothing */", options((empty))) -> bb3; // scope 3 at $DIR/inline_instruction_set.rs:43:14: 43:38
++         asm!("/* do nothing */", options((empty))) -> [return: bb3, unwind unreachable]; // scope 3 at $DIR/inline_instruction_set.rs:43:14: 43:38
       }
   
 -     bb4: {
diff --git a/tests/mir-opt/inline/inline_instruction_set.t32.Inline.diff b/tests/mir-opt/inline/inline_instruction_set.t32.Inline.diff
index e777b2cc29e..36aec4f47b0 100644
--- a/tests/mir-opt/inline/inline_instruction_set.t32.Inline.diff
+++ b/tests/mir-opt/inline/inline_instruction_set.t32.Inline.diff
@@ -14,7 +14,7 @@
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
-          _1 = instruction_set_a32() -> bb1; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
+          _1 = instruction_set_a32() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+1:5: +1:26
                                            // mir::Constant
                                            // + span: $DIR/inline_instruction_set.rs:49:5: 49:24
                                            // + literal: Const { ty: fn() {instruction_set_a32}, val: Value(<ZST>) }
@@ -23,7 +23,7 @@
       bb1: {
           StorageDead(_1);                 // scope 0 at $DIR/inline_instruction_set.rs:+1:26: +1:27
           StorageLive(_2);                 // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
--         _2 = instruction_set_t32() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
+-         _2 = instruction_set_t32() -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+2:5: +2:26
 -                                          // mir::Constant
 -                                          // + span: $DIR/inline_instruction_set.rs:50:5: 50:24
 -                                          // + literal: Const { ty: fn() {instruction_set_t32}, val: Value(<ZST>) }
@@ -32,7 +32,7 @@
 -     bb2: {
           StorageDead(_2);                 // scope 0 at $DIR/inline_instruction_set.rs:+2:26: +2:27
           StorageLive(_3);                 // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
--         _3 = instruction_set_default() -> bb3; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
+-         _3 = instruction_set_default() -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+3:5: +3:30
 -                                          // mir::Constant
 -                                          // + span: $DIR/inline_instruction_set.rs:51:5: 51:28
 -                                          // + literal: Const { ty: fn() {instruction_set_default}, val: Value(<ZST>) }
@@ -41,8 +41,8 @@
 -     bb3: {
           StorageDead(_3);                 // scope 0 at $DIR/inline_instruction_set.rs:+3:30: +3:31
           StorageLive(_4);                 // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
--         _4 = inline_always_and_using_inline_asm() -> bb4; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
-+         _4 = inline_always_and_using_inline_asm() -> bb2; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
+-         _4 = inline_always_and_using_inline_asm() -> [return: bb4, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
++         _4 = inline_always_and_using_inline_asm() -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/inline_instruction_set.rs:+4:5: +4:41
                                            // mir::Constant
                                            // + span: $DIR/inline_instruction_set.rs:52:5: 52:39
                                            // + literal: Const { ty: fn() {inline_always_and_using_inline_asm}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff b/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff
index a4f0ad465e2..a5129e0e8c8 100644
--- a/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff
+++ b/tests/mir-opt/inline/inline_into_box_place.main.Inline.diff
@@ -75,7 +75,7 @@
   
       bb4 (cleanup): {
 -         resume;                          // scope 0 at $DIR/inline_into_box_place.rs:+0:1: +2:2
-+         drop(_2) -> bb2;                 // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
++         drop(_2) -> [return: bb2, unwind terminate]; // scope 3 at $SRC_DIR/alloc/src/boxed.rs:LL:COL
       }
   }
   
diff --git a/tests/mir-opt/inline/inline_options.main.Inline.after.mir b/tests/mir-opt/inline/inline_options.main.Inline.after.mir
index abe26bd8ce3..a2938ead0dc 100644
--- a/tests/mir-opt/inline/inline_options.main.Inline.after.mir
+++ b/tests/mir-opt/inline/inline_options.main.Inline.after.mir
@@ -4,17 +4,17 @@ fn main() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/inline_options.rs:+0:11: +0:11
     let _1: ();                          // in scope 0 at $DIR/inline_options.rs:+1:5: +1:18
     let _2: ();                          // in scope 0 at $DIR/inline_options.rs:+2:5: +2:21
-    scope 1 (inlined inlined::<u32>) {   // at $DIR/inline_options.rs:10:5: 10:21
-        let _3: ();                      // in scope 1 at $DIR/inline_options.rs:16:23: 16:26
-        let _4: ();                      // in scope 1 at $DIR/inline_options.rs:16:28: 16:31
-        let _5: ();                      // in scope 1 at $DIR/inline_options.rs:16:33: 16:36
+    scope 1 (inlined inlined::<u32>) {   // at $DIR/inline_options.rs:11:5: 11:21
+        let _3: ();                      // in scope 1 at $DIR/inline_options.rs:17:23: 17:26
+        let _4: ();                      // in scope 1 at $DIR/inline_options.rs:17:28: 17:31
+        let _5: ();                      // in scope 1 at $DIR/inline_options.rs:17:33: 17:36
     }
 
     bb0: {
         StorageLive(_1);                 // scope 0 at $DIR/inline_options.rs:+1:5: +1:18
         _1 = not_inlined() -> bb1;       // scope 0 at $DIR/inline_options.rs:+1:5: +1:18
                                          // mir::Constant
-                                         // + span: $DIR/inline_options.rs:9:5: 9:16
+                                         // + span: $DIR/inline_options.rs:10:5: 10:16
                                          // + literal: Const { ty: fn() {not_inlined}, val: Value(<ZST>) }
     }
 
@@ -24,9 +24,9 @@ fn main() -> () {
         StorageLive(_3);                 // scope 0 at $DIR/inline_options.rs:+2:5: +2:21
         StorageLive(_4);                 // scope 0 at $DIR/inline_options.rs:+2:5: +2:21
         StorageLive(_5);                 // scope 0 at $DIR/inline_options.rs:+2:5: +2:21
-        _3 = g() -> bb3;                 // scope 1 at $DIR/inline_options.rs:16:23: 16:26
+        _3 = g() -> bb3;                 // scope 1 at $DIR/inline_options.rs:17:23: 17:26
                                          // mir::Constant
-                                         // + span: $DIR/inline_options.rs:16:23: 16:24
+                                         // + span: $DIR/inline_options.rs:17:23: 17:24
                                          // + literal: Const { ty: fn() {g}, val: Value(<ZST>) }
     }
 
@@ -40,16 +40,16 @@ fn main() -> () {
     }
 
     bb3: {
-        _4 = g() -> bb4;                 // scope 1 at $DIR/inline_options.rs:16:28: 16:31
+        _4 = g() -> bb4;                 // scope 1 at $DIR/inline_options.rs:17:28: 17:31
                                          // mir::Constant
-                                         // + span: $DIR/inline_options.rs:16:28: 16:29
+                                         // + span: $DIR/inline_options.rs:17:28: 17:29
                                          // + literal: Const { ty: fn() {g}, val: Value(<ZST>) }
     }
 
     bb4: {
-        _5 = g() -> bb2;                 // scope 1 at $DIR/inline_options.rs:16:33: 16:36
+        _5 = g() -> bb2;                 // scope 1 at $DIR/inline_options.rs:17:33: 17:36
                                          // mir::Constant
-                                         // + span: $DIR/inline_options.rs:16:33: 16:34
+                                         // + span: $DIR/inline_options.rs:17:33: 17:34
                                          // + literal: Const { ty: fn() {g}, val: Value(<ZST>) }
     }
 }
diff --git a/tests/mir-opt/inline/inline_options.rs b/tests/mir-opt/inline/inline_options.rs
index 477f050b69e..f0a89883239 100644
--- a/tests/mir-opt/inline/inline_options.rs
+++ b/tests/mir-opt/inline/inline_options.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Checks that inlining threshold can be controlled with
 // inline-mir-threshold and inline-hint-threshold options.
 //
diff --git a/tests/mir-opt/inline/inline_specialization.main.Inline.diff b/tests/mir-opt/inline/inline_specialization.main.Inline.diff
index af08296edea..9dde9994d1d 100644
--- a/tests/mir-opt/inline/inline_specialization.main.Inline.diff
+++ b/tests/mir-opt/inline/inline_specialization.main.Inline.diff
@@ -7,19 +7,19 @@
       scope 1 {
           debug x => _1;                   // in scope 1 at $DIR/inline_specialization.rs:+1:9: +1:10
       }
-+     scope 2 (inlined <Vec<()> as Foo>::bar) { // at $DIR/inline_specialization.rs:5:13: 5:38
++     scope 2 (inlined <Vec<()> as Foo>::bar) { // at $DIR/inline_specialization.rs:6:13: 6:38
 +     }
   
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/inline_specialization.rs:+1:9: +1:10
 -         _1 = <Vec<()> as Foo>::bar() -> bb1; // scope 0 at $DIR/inline_specialization.rs:+1:13: +1:38
 -                                          // mir::Constant
--                                          // + span: $DIR/inline_specialization.rs:5:13: 5:36
+-                                          // + span: $DIR/inline_specialization.rs:6:13: 6:36
 -                                          // + literal: Const { ty: fn() -> u32 {<Vec<()> as Foo>::bar}, val: Value(<ZST>) }
 -     }
 - 
 -     bb1: {
-+         _1 = const 123_u32;              // scope 2 at $DIR/inline_specialization.rs:14:31: 14:34
++         _1 = const 123_u32;              // scope 2 at $DIR/inline_specialization.rs:15:31: 15:34
           _0 = const ();                   // scope 0 at $DIR/inline_specialization.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/inline_specialization.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/inline_specialization.rs:+2:2: +2:2
diff --git a/tests/mir-opt/inline/inline_specialization.rs b/tests/mir-opt/inline/inline_specialization.rs
index 87275b4e514..c24795e05c6 100644
--- a/tests/mir-opt/inline/inline_specialization.rs
+++ b/tests/mir-opt/inline/inline_specialization.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 #![feature(specialization)]
 
 // EMIT_MIR inline_specialization.main.Inline.diff
diff --git a/tests/mir-opt/inline/inline_trait_method.rs b/tests/mir-opt/inline/inline_trait_method.rs
index 74be53f5512..6aa957eb534 100644
--- a/tests/mir-opt/inline/inline_trait_method.rs
+++ b/tests/mir-opt/inline/inline_trait_method.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // compile-flags: -Z span_free_formats
 
 fn main() {
diff --git a/tests/mir-opt/inline/inline_trait_method.test.Inline.after.mir b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.mir
index 637bf282a65..a9020a5bbb7 100644
--- a/tests/mir-opt/inline/inline_trait_method.test.Inline.after.mir
+++ b/tests/mir-opt/inline/inline_trait_method.test.Inline.after.mir
@@ -10,7 +10,7 @@ fn test(_1: &dyn X) -> u32 {
         _2 = &(*_1);                     // scope 0 at $DIR/inline_trait_method.rs:+1:5: +1:10
         _0 = <dyn X as X>::y(move _2) -> bb1; // scope 0 at $DIR/inline_trait_method.rs:+1:5: +1:10
                                          // mir::Constant
-                                         // + span: $DIR/inline_trait_method.rs:9:7: 9:8
+                                         // + span: $DIR/inline_trait_method.rs:10:7: 10:8
                                          // + literal: Const { ty: for<'a> fn(&'a dyn X) -> u32 {<dyn X as X>::y}, val: Value(<ZST>) }
     }
 
diff --git a/tests/mir-opt/inline/inline_trait_method_2.rs b/tests/mir-opt/inline/inline_trait_method_2.rs
index 378e71a2567..07a60190801 100644
--- a/tests/mir-opt/inline/inline_trait_method_2.rs
+++ b/tests/mir-opt/inline/inline_trait_method_2.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // compile-flags: -Z span_free_formats -Z mir-opt-level=4
 
 // EMIT_MIR inline_trait_method_2.test2.Inline.after.mir
diff --git a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir
index b7c5bbecb68..a4bbecf3b87 100644
--- a/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir
+++ b/tests/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir
@@ -5,8 +5,8 @@ fn test2(_1: &dyn X) -> bool {
     let mut _0: bool;                    // return place in scope 0 at $DIR/inline_trait_method_2.rs:+0:24: +0:28
     let mut _2: &dyn X;                  // in scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11
     let mut _3: &dyn X;                  // in scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11
-    scope 1 (inlined test) {             // at $DIR/inline_trait_method_2.rs:5:5: 5:12
-        debug x => _2;                   // in scope 1 at $DIR/inline_trait_method_2.rs:9:9: 9:10
+    scope 1 (inlined test) {             // at $DIR/inline_trait_method_2.rs:6:5: 6:12
+        debug x => _2;                   // in scope 1 at $DIR/inline_trait_method_2.rs:10:9: 10:10
     }
 
     bb0: {
@@ -15,9 +15,9 @@ fn test2(_1: &dyn X) -> bool {
         _3 = &(*_1);                     // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11
         _2 = move _3 as &dyn X (Pointer(Unsize)); // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11
         StorageDead(_3);                 // scope 0 at $DIR/inline_trait_method_2.rs:+1:10: +1:11
-        _0 = <dyn X as X>::y(_2) -> bb1; // scope 1 at $DIR/inline_trait_method_2.rs:10:5: 10:10
+        _0 = <dyn X as X>::y(_2) -> bb1; // scope 1 at $DIR/inline_trait_method_2.rs:11:5: 11:10
                                          // mir::Constant
-                                         // + span: $DIR/inline_trait_method_2.rs:10:7: 10:8
+                                         // + span: $DIR/inline_trait_method_2.rs:11:7: 11:8
                                          // + literal: Const { ty: for<'a> fn(&'a dyn X) -> bool {<dyn X as X>::y}, val: Value(<ZST>) }
     }
 
diff --git a/tests/mir-opt/inline/issue_106141.outer.Inline.diff b/tests/mir-opt/inline/issue_106141.outer.Inline.diff
index 97361fa5f4c..18df6f9af5f 100644
--- a/tests/mir-opt/inline/issue_106141.outer.Inline.diff
+++ b/tests/mir-opt/inline/issue_106141.outer.Inline.diff
@@ -3,14 +3,14 @@
   
   fn outer() -> usize {
       let mut _0: usize;                   // return place in scope 0 at $DIR/issue_106141.rs:+0:19: +0:24
-+     scope 1 (inlined inner) {            // at $DIR/issue_106141.rs:2:5: 2:12
-+         let mut _1: bool;                // in scope 1 at $DIR/issue_106141.rs:13:8: 13:21
-+         let mut _2: bool;                // in scope 1 at $DIR/issue_106141.rs:13:8: 13:21
-+         let mut _3: &[bool; 1];          // in scope 1 at $DIR/issue_106141.rs:11:18: 11:25
++     scope 1 (inlined inner) {            // at $DIR/issue_106141.rs:3:5: 3:12
++         let mut _1: bool;                // in scope 1 at $DIR/issue_106141.rs:14:8: 14:21
++         let mut _2: bool;                // in scope 1 at $DIR/issue_106141.rs:14:8: 14:21
++         let mut _3: &[bool; 1];          // in scope 1 at $DIR/issue_106141.rs:12:18: 12:25
 +         scope 2 {
-+             debug buffer => _3;          // in scope 2 at $DIR/issue_106141.rs:11:9: 11:15
++             debug buffer => _3;          // in scope 2 at $DIR/issue_106141.rs:12:9: 12:15
 +             scope 3 {
-+                 debug index => _0;       // in scope 3 at $DIR/issue_106141.rs:12:9: 12:14
++                 debug index => _0;       // in scope 3 at $DIR/issue_106141.rs:13:9: 13:14
 +             }
 +         }
 +     }
@@ -18,36 +18,36 @@
       bb0: {
 -         _0 = inner() -> bb1;             // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12
 +         StorageLive(_3);                 // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12
-+         _3 = const _;                    // scope 1 at $DIR/issue_106141.rs:11:18: 11:25
++         _3 = const _;                    // scope 1 at $DIR/issue_106141.rs:12:18: 12:25
                                            // mir::Constant
--                                          // + span: $DIR/issue_106141.rs:2:5: 2:10
+-                                          // + span: $DIR/issue_106141.rs:3:5: 3:10
 -                                          // + literal: Const { ty: fn() -> usize {inner}, val: Value(<ZST>) }
-+                                          // + span: $DIR/issue_106141.rs:11:18: 11:25
++                                          // + span: $DIR/issue_106141.rs:12:18: 12:25
 +                                          // + literal: Const { ty: &[bool; 1], val: Unevaluated(inner, [], Some(promoted[0])) }
-+         _0 = index() -> bb1;             // scope 2 at $DIR/issue_106141.rs:12:17: 12:24
++         _0 = index() -> bb1;             // scope 2 at $DIR/issue_106141.rs:13:17: 13:24
 +                                          // mir::Constant
-+                                          // + span: $DIR/issue_106141.rs:12:17: 12:22
++                                          // + span: $DIR/issue_106141.rs:13:17: 13:22
 +                                          // + literal: Const { ty: fn() -> usize {index}, val: Value(<ZST>) }
       }
   
       bb1: {
-+         StorageLive(_1);                 // scope 3 at $DIR/issue_106141.rs:13:8: 13:21
-+         _2 = Lt(_0, const 1_usize);      // scope 3 at $DIR/issue_106141.rs:13:8: 13:21
-+         assert(move _2, "index out of bounds: the length is {} but the index is {}", const 1_usize, _0) -> bb2; // scope 3 at $DIR/issue_106141.rs:13:8: 13:21
++         StorageLive(_1);                 // scope 3 at $DIR/issue_106141.rs:14:8: 14:21
++         _2 = Lt(_0, const 1_usize);      // scope 3 at $DIR/issue_106141.rs:14:8: 14:21
++         assert(move _2, "index out of bounds: the length is {} but the index is {}", const 1_usize, _0) -> bb2; // scope 3 at $DIR/issue_106141.rs:14:8: 14:21
 +     }
 + 
 +     bb2: {
-+         _1 = (*_3)[_0];                  // scope 3 at $DIR/issue_106141.rs:13:8: 13:21
-+         switchInt(move _1) -> [0: bb3, otherwise: bb4]; // scope 3 at $DIR/issue_106141.rs:13:8: 13:21
++         _1 = (*_3)[_0];                  // scope 3 at $DIR/issue_106141.rs:14:8: 14:21
++         switchInt(move _1) -> [0: bb3, otherwise: bb4]; // scope 3 at $DIR/issue_106141.rs:14:8: 14:21
 +     }
 + 
 +     bb3: {
-+         _0 = const 0_usize;              // scope 3 at $DIR/issue_106141.rs:16:9: 16:10
-+         goto -> bb4;                     // scope 3 at $DIR/issue_106141.rs:13:5: 17:6
++         _0 = const 0_usize;              // scope 3 at $DIR/issue_106141.rs:17:9: 17:10
++         goto -> bb4;                     // scope 3 at $DIR/issue_106141.rs:14:5: 18:6
 +     }
 + 
 +     bb4: {
-+         StorageDead(_1);                 // scope 3 at $DIR/issue_106141.rs:17:5: 17:6
++         StorageDead(_1);                 // scope 3 at $DIR/issue_106141.rs:18:5: 18:6
 +         StorageDead(_3);                 // scope 0 at $DIR/issue_106141.rs:+1:5: +1:12
           return;                          // scope 0 at $DIR/issue_106141.rs:+2:2: +2:2
       }
diff --git a/tests/mir-opt/inline/issue_106141.rs b/tests/mir-opt/inline/issue_106141.rs
index c8288b7f341..b6bd806e6fc 100644
--- a/tests/mir-opt/inline/issue_106141.rs
+++ b/tests/mir-opt/inline/issue_106141.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 pub fn outer() -> usize {
     inner()
 }
diff --git a/tests/mir-opt/inline/issue_78442.bar.Inline.diff b/tests/mir-opt/inline/issue_78442.bar.Inline.diff
index aa62e4a165e..dc3fe75559e 100644
--- a/tests/mir-opt/inline/issue_78442.bar.Inline.diff
+++ b/tests/mir-opt/inline/issue_78442.bar.Inline.diff
@@ -46,11 +46,11 @@
 -     bb3: {
 -         return;                          // scope 0 at $DIR/issue_78442.rs:+5:2: +5:2
 +     bb3 (cleanup): {
-+         drop(_1) -> bb4;                 // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2
++         drop(_1) -> [return: bb4, unwind terminate]; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2
       }
   
       bb4 (cleanup): {
--         drop(_1) -> bb5;                 // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2
+-         drop(_1) -> [return: bb5, unwind terminate]; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2
 +         resume;                          // scope 0 at $DIR/issue_78442.rs:+0:1: +5:2
       }
   
diff --git a/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff b/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff
index 21055c6bfb5..8f56ef2585c 100644
--- a/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff
+++ b/tests/mir-opt/inline/issue_78442.bar.RevealAll.diff
@@ -47,7 +47,7 @@
       }
   
       bb4 (cleanup): {
-          drop(_1) -> bb5;                 // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2
+          drop(_1) -> [return: bb5, unwind terminate]; // scope 0 at $DIR/issue_78442.rs:+5:1: +5:2
       }
   
       bb5 (cleanup): {
diff --git a/tests/mir-opt/inline/unchecked_shifts.rs b/tests/mir-opt/inline/unchecked_shifts.rs
index e55fa745abc..17724530d65 100644
--- a/tests/mir-opt/inline/unchecked_shifts.rs
+++ b/tests/mir-opt/inline/unchecked_shifts.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 #![crate_type = "lib"]
 #![feature(unchecked_math)]
 
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 5fd918b3aa5..6184a0acd18 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
@@ -7,43 +7,52 @@
       let mut _0: u16;                     // return place in scope 0 at $DIR/unchecked_shifts.rs:+0:65: +0:68
       let mut _3: u16;                     // in scope 0 at $DIR/unchecked_shifts.rs:+1:5: +1:6
       let mut _4: u32;                     // in scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
-+     scope 1 (inlined core::num::<impl u16>::unchecked_shl) { // at $DIR/unchecked_shifts.rs:10:7: 10:23
++     scope 1 (inlined core::num::<impl u16>::unchecked_shl) { // at $DIR/unchecked_shifts.rs:11:7: 11:23
 +         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/uint_macros.rs:LL:COL
 +         let mut _6: std::option::Option<u16>; // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +         let mut _7: std::result::Result<u16, std::num::TryFromIntError>; // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +         scope 2 {
-+             scope 3 (inlined Result::<u16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+                 debug self => _7;        // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+                 let mut _8: isize;       // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+                 let _9: u16;             // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+                 scope 4 {
-+                     debug x => _9;       // in scope 4 at $SRC_DIR/core/src/result.rs:LL:COL
++             scope 3 (inlined <u32 as TryInto<u16>>::try_into) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++                 debug self => _4;        // in scope 3 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
++                 scope 4 (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 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                     let mut _8: bool;    // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                     let mut _9: u32;     // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                     let mut _10: u16;    // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
 +                 }
-+                 scope 5 {
-+                     scope 6 {
-+                         debug x => const TryFromIntError(()); // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
++             }
++             scope 5 (inlined Result::<u16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++                 debug self => _7;        // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++                 let mut _11: isize;      // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++                 let _12: u16;            // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++                 scope 6 {
++                     debug x => _12;      // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
++                 }
++                 scope 7 {
++                     scope 8 {
++                         debug x => const TryFromIntError(()); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
 +                     }
 +                 }
 +             }
-+             scope 7 (inlined #[track_caller] Option::<u16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+                 debug self => _6;        // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+                 let mut _10: &std::option::Option<u16>; // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+                 let mut _11: isize;      // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+                 scope 8 {
-+                     debug val => _5;     // in scope 8 at $SRC_DIR/core/src/option.rs:LL:COL
++             scope 9 (inlined #[track_caller] Option::<u16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/uint_macros.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
 +                 }
-+                 scope 9 {
-+                     scope 11 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
-+                         scope 12 {
-+                             scope 13 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
++                 scope 11 {
++                     scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
++                         scope 14 {
++                             scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
 +                             }
 +                         }
 +                     }
 +                 }
-+                 scope 10 (inlined Option::<u16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
-+                     debug self => _10;   // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
++                 scope 12 (inlined Option::<u16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
++                     debug self => _13;   // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
 +                 }
 +             }
 +         }
@@ -55,58 +64,78 @@
           StorageLive(_4);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
           _4 = _2;                         // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
 -         _0 = core::num::<impl u16>::unchecked_shl(move _3, move _4) -> bb1; // scope 0 at $DIR/unchecked_shifts.rs:+1:5: +1:23
+-                                          // mir::Constant
+-                                          // + 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/uint_macros.rs:LL:COL
 +         StorageLive(_6);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +         StorageLive(_7);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+         _7 = <u32 as TryInto<u16>>::try_into(_4) -> bb1; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-                                           // mir::Constant
--                                          // + span: $DIR/unchecked_shifts.rs:10:7: 10:20
--                                          // + literal: Const { ty: unsafe fn(u16, u32) -> u16 {core::num::<impl u16>::unchecked_shl}, val: Value(<ZST>) }
-+                                          // + span: $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+                                          // + literal: Const { ty: fn(u32) -> Result<u16, <u32 as TryInto<u16>>::Error> {<u32 as TryInto<u16>>::try_into}, val: Value(<ZST>) }
++         StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_9);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _9 = const 65535_u32;            // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _8 = Gt(_4, move _9);            // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         switchInt(move _8) -> [0: bb4, otherwise: bb3]; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
       }
   
       bb1: {
-+         StorageLive(_9);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+         _8 = discriminant(_7);           // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+         switchInt(move _8) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+     }
-+ 
-+     bb2: {
-+         StorageDead(_9);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++         StorageDead(_12);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +         StorageDead(_7);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+         StorageLive(_10);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+         _11 = discriminant(_6);          // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+         switchInt(move _11) -> [1: bb7, otherwise: bb5]; // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
++         StorageLive(_13);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++         _14 = discriminant(_6);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         switchInt(move _14) -> [1: bb9, otherwise: bb7]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
 +     }
 + 
-+     bb3: {
++     bb2: {
 +         StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
           StorageDead(_4);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23
           StorageDead(_3);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23
           return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
 +     }
 + 
++     bb3: {
++         _7 = Result::<u16, TryFromIntError>::Err(const TryFromIntError(())); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                                          // mir::Constant
++                                          // + span: no-location
++                                          // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
++         goto -> bb5;                     // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++     }
++ 
 +     bb4: {
-+         _6 = Option::<u16>::None;        // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
-+         goto -> bb2;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++         StorageLive(_10);                // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _10 = _4 as u16 (IntToInt);      // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _7 = Result::<u16, TryFromIntError>::Ok(move _10); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_10);                // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         goto -> bb5;                     // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
 +     }
 + 
 +     bb5: {
-+         unreachable;                     // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
++         StorageDead(_8);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_12);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++         _11 = discriminant(_7);          // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++         switchInt(move _11) -> [0: bb8, 1: bb6, otherwise: bb7]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
 +     }
 + 
 +     bb6: {
-+         _9 = move ((_7 as Ok).0: u16);   // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+         _6 = Option::<u16>::Some(move _9); // scope 4 at $SRC_DIR/core/src/result.rs:LL:COL
-+         goto -> bb2;                     // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
++         _6 = Option::<u16>::None;        // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
++         goto -> bb1;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
 +     }
 + 
 +     bb7: {
-+         _5 = move ((_6 as Some).0: u16); // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+         StorageDead(_10);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++         unreachable;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb8: {
++         _12 = move ((_7 as Ok).0: u16);  // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++         _6 = Option::<u16>::Some(move _12); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
++         goto -> bb1;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb9: {
++         _5 = move ((_6 as Some).0: u16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         StorageDead(_13);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
 +         StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-+         _0 = unchecked_shl::<u16>(_3, move _5) -> bb3; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
++         _0 = unchecked_shl::<u16>(_3, move _5) -> [return: bb2, 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>) }
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 c5501cef743..726b6bbf93b 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
@@ -4,43 +4,52 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
     debug a => _1;                       // in scope 0 at $DIR/unchecked_shifts.rs:+0:46: +0:47
     debug b => _2;                       // in scope 0 at $DIR/unchecked_shifts.rs:+0:54: +0:55
     let mut _0: u16;                     // return place in scope 0 at $DIR/unchecked_shifts.rs:+0:65: +0:68
-    scope 1 (inlined core::num::<impl u16>::unchecked_shl) { // at $DIR/unchecked_shifts.rs:10:7: 10:23
+    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: u16;                 // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
         let mut _4: std::option::Option<u16>; // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
         let mut _5: std::result::Result<u16, std::num::TryFromIntError>; // in scope 1 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
         scope 2 {
-            scope 3 (inlined Result::<u16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-                debug self => _5;        // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-                let mut _6: isize;       // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-                let _7: u16;             // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-                scope 4 {
-                    debug x => _7;       // in scope 4 at $SRC_DIR/core/src/result.rs:LL:COL
+            scope 3 (inlined <u32 as TryInto<u16>>::try_into) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+                debug self => _2;        // in scope 3 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                scope 4 (inlined convert::num::<impl TryFrom<u32> for u16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                    debug u => _2;       // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                    let mut _6: bool;    // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                    let mut _7: u32;     // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                    let mut _8: u16;     // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
                 }
-                scope 5 {
-                    scope 6 {
-                        debug x => const TryFromIntError(()); // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+            }
+            scope 5 (inlined Result::<u16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+                debug self => _5;        // 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: u16;            // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+                scope 6 {
+                    debug x => _10;      // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+                }
+                scope 7 {
+                    scope 8 {
+                        debug x => const TryFromIntError(()); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
                     }
                 }
             }
-            scope 7 (inlined #[track_caller] Option::<u16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-                debug self => _4;        // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-                let mut _8: &std::option::Option<u16>; // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-                let mut _9: isize;       // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-                scope 8 {
-                    debug val => _3;     // in scope 8 at $SRC_DIR/core/src/option.rs:LL:COL
+            scope 9 (inlined #[track_caller] Option::<u16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+                debug self => _4;        // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                let mut _11: &std::option::Option<u16>; // 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
+                scope 10 {
+                    debug val => _3;     // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
                 }
-                scope 9 {
-                    scope 11 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
-                        scope 12 {
-                            scope 13 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                scope 11 {
+                    scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                        scope 14 {
+                            scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                             }
                         }
                     }
                 }
-                scope 10 (inlined Option::<u16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
-                    debug self => _8;    // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
+                scope 12 (inlined Option::<u16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                    debug self => _11;   // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
                 }
             }
         }
@@ -50,51 +59,70 @@ fn unchecked_shl_unsigned_smaller(_1: u16, _2: u32) -> u16 {
         StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
         StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
         StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-        _5 = <u32 as TryInto<u16>>::try_into(_2) -> bb1; // 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: fn(u32) -> Result<u16, <u32 as TryInto<u16>>::Error> {<u32 as TryInto<u16>>::try_into}, val: Value(<ZST>) }
+        StorageLive(_6);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_7);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _7 = const 65535_u32;            // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _6 = Gt(_2, move _7);            // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_7);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        switchInt(move _6) -> [0: bb4, otherwise: bb3]; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb1: {
-        StorageLive(_7);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-        _6 = discriminant(_5);           // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-        switchInt(move _6) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
+        StorageDead(_10);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        StorageLive(_11);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        _12 = discriminant(_4);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        switchInt(move _12) -> [1: bb9, otherwise: bb7]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
     }
 
     bb2: {
-        StorageDead(_7);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-        StorageLive(_8);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-        _9 = discriminant(_4);           // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-        switchInt(move _9) -> [1: bb7, otherwise: bb5]; // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_3);                 // 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
     }
 
     bb3: {
-        StorageDead(_3);                 // 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
+        _5 = Result::<u16, TryFromIntError>::Err(const TryFromIntError(())); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: no-location
+                                         // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
+        goto -> bb5;                     // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb4: {
-        _4 = Option::<u16>::None;        // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
-        goto -> bb2;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+        StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _8 = _2 as u16 (IntToInt);       // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _5 = Result::<u16, TryFromIntError>::Ok(move _8); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_8);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        goto -> bb5;                     // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb5: {
-        unreachable;                     // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
+        StorageDead(_6);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_10);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        _9 = discriminant(_5);           // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+        switchInt(move _9) -> [0: bb8, 1: bb6, otherwise: bb7]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb6: {
-        _7 = move ((_5 as Ok).0: u16);   // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-        _4 = Option::<u16>::Some(move _7); // scope 4 at $SRC_DIR/core/src/result.rs:LL:COL
-        goto -> bb2;                     // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
+        _4 = Option::<u16>::None;        // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb1;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb7: {
-        _3 = move ((_4 as Some).0: u16); // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-        StorageDead(_8);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        unreachable;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb8: {
+        _10 = move ((_5 as Ok).0: u16);  // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+        _4 = Option::<u16>::Some(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
+    }
+
+    bb9: {
+        _3 = move ((_4 as Some).0: u16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_11);                // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
         StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
-        _0 = unchecked_shl::<u16>(_1, move _3) -> bb3; // scope 2 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+        _0 = unchecked_shl::<u16>(_1, move _3) -> [return: bb2, 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>) }
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 68d3b21fc2a..35d5b6e72f2 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
@@ -7,43 +7,52 @@
       let mut _0: i16;                     // return place in scope 0 at $DIR/unchecked_shifts.rs:+0:63: +0:66
       let mut _3: i16;                     // in scope 0 at $DIR/unchecked_shifts.rs:+1:5: +1:6
       let mut _4: u32;                     // in scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
-+     scope 1 (inlined core::num::<impl i16>::unchecked_shr) { // at $DIR/unchecked_shifts.rs:16:7: 16:23
++     scope 1 (inlined core::num::<impl i16>::unchecked_shr) { // at $DIR/unchecked_shifts.rs:17:7: 17:23
 +         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/int_macros.rs:LL:COL
 +         let mut _6: std::option::Option<i16>; // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +         let mut _7: std::result::Result<i16, std::num::TryFromIntError>; // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +         scope 2 {
-+             scope 3 (inlined Result::<i16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+                 debug self => _7;        // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+                 let mut _8: isize;       // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+                 let _9: i16;             // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+                 scope 4 {
-+                     debug x => _9;       // in scope 4 at $SRC_DIR/core/src/result.rs:LL:COL
++             scope 3 (inlined <u32 as TryInto<i16>>::try_into) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++                 debug self => _4;        // in scope 3 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
++                 scope 4 (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 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                     let mut _8: bool;    // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                     let mut _9: u32;     // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                     let mut _10: i16;    // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
 +                 }
-+                 scope 5 {
-+                     scope 6 {
-+                         debug x => const TryFromIntError(()); // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
++             }
++             scope 5 (inlined Result::<i16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++                 debug self => _7;        // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++                 let mut _11: isize;      // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++                 let _12: i16;            // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++                 scope 6 {
++                     debug x => _12;      // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
++                 }
++                 scope 7 {
++                     scope 8 {
++                         debug x => const TryFromIntError(()); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
 +                     }
 +                 }
 +             }
-+             scope 7 (inlined #[track_caller] Option::<i16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+                 debug self => _6;        // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+                 let mut _10: &std::option::Option<i16>; // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+                 let mut _11: isize;      // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+                 scope 8 {
-+                     debug val => _5;     // in scope 8 at $SRC_DIR/core/src/option.rs:LL:COL
++             scope 9 (inlined #[track_caller] Option::<i16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/int_macros.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
 +                 }
-+                 scope 9 {
-+                     scope 11 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
-+                         scope 12 {
-+                             scope 13 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
++                 scope 11 {
++                     scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
++                         scope 14 {
++                             scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
 +                             }
 +                         }
 +                     }
 +                 }
-+                 scope 10 (inlined Option::<i16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
-+                     debug self => _10;   // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
++                 scope 12 (inlined Option::<i16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
++                     debug self => _13;   // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
 +                 }
 +             }
 +         }
@@ -55,58 +64,78 @@
           StorageLive(_4);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
           _4 = _2;                         // scope 0 at $DIR/unchecked_shifts.rs:+1:21: +1:22
 -         _0 = core::num::<impl i16>::unchecked_shr(move _3, move _4) -> bb1; // scope 0 at $DIR/unchecked_shifts.rs:+1:5: +1:23
+-                                          // mir::Constant
+-                                          // + 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/int_macros.rs:LL:COL
 +         StorageLive(_6);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +         StorageLive(_7);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+         _7 = <u32 as TryInto<i16>>::try_into(_4) -> bb1; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-                                           // mir::Constant
--                                          // + span: $DIR/unchecked_shifts.rs:16:7: 16:20
--                                          // + literal: Const { ty: unsafe fn(i16, u32) -> i16 {core::num::<impl i16>::unchecked_shr}, val: Value(<ZST>) }
-+                                          // + span: $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+                                          // + literal: Const { ty: fn(u32) -> Result<i16, <u32 as TryInto<i16>>::Error> {<u32 as TryInto<i16>>::try_into}, val: Value(<ZST>) }
++         StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_9);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _9 = const 32767_u32;            // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _8 = Gt(_4, move _9);            // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_9);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         switchInt(move _8) -> [0: bb4, otherwise: bb3]; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
       }
   
       bb1: {
-+         StorageLive(_9);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+         _8 = discriminant(_7);           // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+         switchInt(move _8) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+     }
-+ 
-+     bb2: {
-+         StorageDead(_9);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++         StorageDead(_12);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +         StorageDead(_7);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+         StorageLive(_10);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+         _11 = discriminant(_6);          // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+         switchInt(move _11) -> [1: bb7, otherwise: bb5]; // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
++         StorageLive(_13);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++         _14 = discriminant(_6);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         switchInt(move _14) -> [1: bb9, otherwise: bb7]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
 +     }
 + 
-+     bb3: {
++     bb2: {
 +         StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
           StorageDead(_4);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23
           StorageDead(_3);                 // scope 0 at $DIR/unchecked_shifts.rs:+1:22: +1:23
           return;                          // scope 0 at $DIR/unchecked_shifts.rs:+2:2: +2:2
 +     }
 + 
++     bb3: {
++         _7 = Result::<i16, TryFromIntError>::Err(const TryFromIntError(())); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++                                          // mir::Constant
++                                          // + span: no-location
++                                          // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
++         goto -> bb5;                     // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++     }
++ 
 +     bb4: {
-+         _6 = Option::<i16>::None;        // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
-+         goto -> bb2;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++         StorageLive(_10);                // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _10 = _4 as i16 (IntToInt);      // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         _7 = Result::<i16, TryFromIntError>::Ok(move _10); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageDead(_10);                // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         goto -> bb5;                     // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
 +     }
 + 
 +     bb5: {
-+         unreachable;                     // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
++         StorageDead(_8);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
++         StorageLive(_12);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++         _11 = discriminant(_7);          // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++         switchInt(move _11) -> [0: bb8, 1: bb6, otherwise: bb7]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
 +     }
 + 
 +     bb6: {
-+         _9 = move ((_7 as Ok).0: i16);   // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-+         _6 = Option::<i16>::Some(move _9); // scope 4 at $SRC_DIR/core/src/result.rs:LL:COL
-+         goto -> bb2;                     // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
++         _6 = Option::<i16>::None;        // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
++         goto -> bb1;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
 +     }
 + 
 +     bb7: {
-+         _5 = move ((_6 as Some).0: i16); // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-+         StorageDead(_10);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++         unreachable;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb8: {
++         _12 = move ((_7 as Ok).0: i16);  // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++         _6 = Option::<i16>::Some(move _12); // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
++         goto -> bb1;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++     }
++ 
++     bb9: {
++         _5 = move ((_6 as Some).0: i16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
++         StorageDead(_13);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
 +         StorageDead(_6);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-+         _0 = unchecked_shr::<i16>(_3, move _5) -> bb3; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
++         _0 = unchecked_shr::<i16>(_3, move _5) -> [return: bb2, 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>) }
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 ed3a89ceace..b006085b54c 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
@@ -4,43 +4,52 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
     debug a => _1;                       // in scope 0 at $DIR/unchecked_shifts.rs:+0:44: +0:45
     debug b => _2;                       // in scope 0 at $DIR/unchecked_shifts.rs:+0:52: +0:53
     let mut _0: i16;                     // return place in scope 0 at $DIR/unchecked_shifts.rs:+0:63: +0:66
-    scope 1 (inlined core::num::<impl i16>::unchecked_shr) { // at $DIR/unchecked_shifts.rs:16:7: 16:23
+    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: i16;                 // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
         let mut _4: std::option::Option<i16>; // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
         let mut _5: std::result::Result<i16, std::num::TryFromIntError>; // in scope 1 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
         scope 2 {
-            scope 3 (inlined Result::<i16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-                debug self => _5;        // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-                let mut _6: isize;       // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-                let _7: i16;             // in scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-                scope 4 {
-                    debug x => _7;       // in scope 4 at $SRC_DIR/core/src/result.rs:LL:COL
+            scope 3 (inlined <u32 as TryInto<i16>>::try_into) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+                debug self => _2;        // in scope 3 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                scope 4 (inlined convert::num::<impl TryFrom<u32> for i16>::try_from) { // at $SRC_DIR/core/src/convert/mod.rs:LL:COL
+                    debug u => _2;       // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                    let mut _6: bool;    // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                    let mut _7: u32;     // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                    let mut _8: i16;     // in scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
                 }
-                scope 5 {
-                    scope 6 {
-                        debug x => const TryFromIntError(()); // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+            }
+            scope 5 (inlined Result::<i16, TryFromIntError>::ok) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+                debug self => _5;        // 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: i16;            // in scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+                scope 6 {
+                    debug x => _10;      // in scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
+                }
+                scope 7 {
+                    scope 8 {
+                        debug x => const TryFromIntError(()); // in scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
                     }
                 }
             }
-            scope 7 (inlined #[track_caller] Option::<i16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-                debug self => _4;        // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-                let mut _8: &std::option::Option<i16>; // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-                let mut _9: isize;       // in scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-                scope 8 {
-                    debug val => _3;     // in scope 8 at $SRC_DIR/core/src/option.rs:LL:COL
+            scope 9 (inlined #[track_caller] Option::<i16>::unwrap_unchecked) { // at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+                debug self => _4;        // in scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+                let mut _11: &std::option::Option<i16>; // 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
+                scope 10 {
+                    debug val => _3;     // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
                 }
-                scope 9 {
-                    scope 11 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
-                        scope 12 {
-                            scope 13 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
+                scope 11 {
+                    scope 13 (inlined unreachable_unchecked) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                        scope 14 {
+                            scope 15 (inlined unreachable_unchecked::runtime) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL
                             }
                         }
                     }
                 }
-                scope 10 (inlined Option::<i16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
-                    debug self => _8;    // in scope 10 at $SRC_DIR/core/src/option.rs:LL:COL
+                scope 12 (inlined Option::<i16>::is_some) { // at $SRC_DIR/core/src/option.rs:LL:COL
+                    debug self => _11;   // in scope 12 at $SRC_DIR/core/src/option.rs:LL:COL
                 }
             }
         }
@@ -50,51 +59,70 @@ fn unchecked_shr_signed_smaller(_1: i16, _2: u32) -> i16 {
         StorageLive(_3);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
         StorageLive(_4);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
         StorageLive(_5);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-        _5 = <u32 as TryInto<i16>>::try_into(_2) -> bb1; // 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: fn(u32) -> Result<i16, <u32 as TryInto<i16>>::Error> {<u32 as TryInto<i16>>::try_into}, val: Value(<ZST>) }
+        StorageLive(_6);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_7);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _7 = const 32767_u32;            // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _6 = Gt(_2, move _7);            // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_7);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        switchInt(move _6) -> [0: bb4, otherwise: bb3]; // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb1: {
-        StorageLive(_7);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-        _6 = discriminant(_5);           // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-        switchInt(move _6) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
+        StorageDead(_10);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+        StorageLive(_11);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+        _12 = discriminant(_4);          // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        switchInt(move _12) -> [1: bb9, otherwise: bb7]; // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
     }
 
     bb2: {
-        StorageDead(_7);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-        StorageDead(_5);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-        StorageLive(_8);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-        _9 = discriminant(_4);           // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-        switchInt(move _9) -> [1: bb7, otherwise: bb5]; // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_3);                 // 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
     }
 
     bb3: {
-        StorageDead(_3);                 // 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
+        _5 = Result::<i16, TryFromIntError>::Err(const TryFromIntError(())); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+                                         // mir::Constant
+                                         // + span: no-location
+                                         // + literal: Const { ty: TryFromIntError, val: Value(<ZST>) }
+        goto -> bb5;                     // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb4: {
-        _4 = Option::<i16>::None;        // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
-        goto -> bb2;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+        StorageLive(_8);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _8 = _2 as i16 (IntToInt);       // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        _5 = Result::<i16, TryFromIntError>::Ok(move _8); // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageDead(_8);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        goto -> bb5;                     // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
     }
 
     bb5: {
-        unreachable;                     // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
+        StorageDead(_6);                 // scope 4 at $SRC_DIR/core/src/convert/num.rs:LL:COL
+        StorageLive(_10);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+        _9 = discriminant(_5);           // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+        switchInt(move _9) -> [0: bb8, 1: bb6, otherwise: bb7]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb6: {
-        _7 = move ((_5 as Ok).0: i16);   // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
-        _4 = Option::<i16>::Some(move _7); // scope 4 at $SRC_DIR/core/src/result.rs:LL:COL
-        goto -> bb2;                     // scope 3 at $SRC_DIR/core/src/result.rs:LL:COL
+        _4 = Option::<i16>::None;        // scope 8 at $SRC_DIR/core/src/result.rs:LL:COL
+        goto -> bb1;                     // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
     }
 
     bb7: {
-        _3 = move ((_4 as Some).0: i16); // scope 7 at $SRC_DIR/core/src/option.rs:LL:COL
-        StorageDead(_8);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+        unreachable;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+    }
+
+    bb8: {
+        _10 = move ((_5 as Ok).0: i16);  // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+        _4 = Option::<i16>::Some(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
+    }
+
+    bb9: {
+        _3 = move ((_4 as Some).0: i16); // scope 9 at $SRC_DIR/core/src/option.rs:LL:COL
+        StorageDead(_11);                // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
         StorageDead(_4);                 // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
-        _0 = unchecked_shr::<i16>(_1, move _3) -> bb3; // scope 2 at $SRC_DIR/core/src/num/int_macros.rs:LL:COL
+        _0 = unchecked_shr::<i16>(_1, move _3) -> [return: bb2, 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>) }
diff --git a/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff
index 2f6f5f87efc..49006e012dd 100644
--- a/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff
+++ b/tests/mir-opt/instrument_coverage.main.InstrumentCoverage.diff
@@ -14,7 +14,7 @@
   
       bb1: {
 +         Coverage::Expression(4294967295) = 1 + 2 for /the/src/instrument_coverage.rs:12:5 - 13:17; // scope 0 at /the/src/instrument_coverage.rs:+1:5: +5:6
-          falseUnwind -> [real: bb2, cleanup: bb6]; // scope 0 at /the/src/instrument_coverage.rs:+1:5: +5:6
+          falseUnwind -> [real: bb2, unwind: bb6]; // scope 0 at /the/src/instrument_coverage.rs:+1:5: +5:6
       }
   
       bb2: {
diff --git a/tests/mir-opt/intrinsic_asserts.generic.InstCombine.diff b/tests/mir-opt/intrinsic_asserts.generic.InstCombine.diff
index 7031c3f3e69..09fc145e734 100644
--- a/tests/mir-opt/intrinsic_asserts.generic.InstCombine.diff
+++ b/tests/mir-opt/intrinsic_asserts.generic.InstCombine.diff
@@ -9,7 +9,7 @@
   
       bb0: {
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:46
-          _1 = assert_inhabited::<T>() -> bb1; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:46
+          _1 = assert_inhabited::<T>() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:46
                                            // mir::Constant
                                            // + span: $DIR/intrinsic_asserts.rs:25:5: 25:44
                                            // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_inhabited::<T>}, val: Value(<ZST>) }
@@ -18,7 +18,7 @@
       bb1: {
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+1:46: +1:47
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:47
-          _2 = assert_zero_valid::<T>() -> bb2; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:47
+          _2 = assert_zero_valid::<T>() -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:47
                                            // mir::Constant
                                            // + span: $DIR/intrinsic_asserts.rs:26:5: 26:45
                                            // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_zero_valid::<T>}, val: Value(<ZST>) }
@@ -27,7 +27,7 @@
       bb2: {
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+2:47: +2:48
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:60
-          _3 = assert_mem_uninitialized_valid::<T>() -> bb3; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:60
+          _3 = assert_mem_uninitialized_valid::<T>() -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:60
                                            // mir::Constant
                                            // + span: $DIR/intrinsic_asserts.rs:27:5: 27:58
                                            // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_mem_uninitialized_valid::<T>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/intrinsic_asserts.panics.InstCombine.diff b/tests/mir-opt/intrinsic_asserts.panics.InstCombine.diff
index 4caa9971fef..c52174ef5ea 100644
--- a/tests/mir-opt/intrinsic_asserts.panics.InstCombine.diff
+++ b/tests/mir-opt/intrinsic_asserts.panics.InstCombine.diff
@@ -9,8 +9,8 @@
   
       bb0: {
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:50
--         _1 = assert_inhabited::<Never>() -> bb1; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:50
-+         _1 = assert_inhabited::<Never>(); // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:50
+-         _1 = assert_inhabited::<Never>() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:50
++         _1 = assert_inhabited::<Never>() -> unwind unreachable; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:50
                                            // mir::Constant
                                            // + span: $DIR/intrinsic_asserts.rs:17:5: 17:48
                                            // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_inhabited::<Never>}, val: Value(<ZST>) }
@@ -19,8 +19,8 @@
       bb1: {
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+1:50: +1:51
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:49
--         _2 = assert_zero_valid::<&u8>() -> bb2; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:49
-+         _2 = assert_zero_valid::<&u8>(); // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:49
+-         _2 = assert_zero_valid::<&u8>() -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:49
++         _2 = assert_zero_valid::<&u8>() -> unwind unreachable; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:49
                                            // mir::Constant
                                            // + span: $DIR/intrinsic_asserts.rs:18:5: 18:47
                                            // + user_ty: UserType(0)
@@ -30,8 +30,8 @@
       bb2: {
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+2:49: +2:50
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:62
--         _3 = assert_mem_uninitialized_valid::<&u8>() -> bb3; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:62
-+         _3 = assert_mem_uninitialized_valid::<&u8>(); // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:62
+-         _3 = assert_mem_uninitialized_valid::<&u8>() -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:62
++         _3 = assert_mem_uninitialized_valid::<&u8>() -> unwind unreachable; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:62
                                            // mir::Constant
                                            // + span: $DIR/intrinsic_asserts.rs:19:5: 19:60
                                            // + user_ty: UserType(1)
diff --git a/tests/mir-opt/intrinsic_asserts.removable.InstCombine.diff b/tests/mir-opt/intrinsic_asserts.removable.InstCombine.diff
index b0bec957369..d059d47ee58 100644
--- a/tests/mir-opt/intrinsic_asserts.removable.InstCombine.diff
+++ b/tests/mir-opt/intrinsic_asserts.removable.InstCombine.diff
@@ -9,7 +9,7 @@
   
       bb0: {
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:47
--         _1 = assert_inhabited::<()>() -> bb1; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:47
+-         _1 = assert_inhabited::<()>() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+1:5: +1:47
 -                                          // mir::Constant
 -                                          // + span: $DIR/intrinsic_asserts.rs:7:5: 7:45
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_inhabited::<()>}, val: Value(<ZST>) }
@@ -19,7 +19,7 @@
       bb1: {
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+1:47: +1:48
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:48
--         _2 = assert_zero_valid::<u8>() -> bb2; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:48
+-         _2 = assert_zero_valid::<u8>() -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+2:5: +2:48
 -                                          // mir::Constant
 -                                          // + span: $DIR/intrinsic_asserts.rs:8:5: 8:46
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_zero_valid::<u8>}, val: Value(<ZST>) }
@@ -29,7 +29,7 @@
       bb2: {
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+2:48: +2:49
           nop;                             // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:61
--         _3 = assert_mem_uninitialized_valid::<u8>() -> bb3; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:61
+-         _3 = assert_mem_uninitialized_valid::<u8>() -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/intrinsic_asserts.rs:+3:5: +3:61
 -                                          // mir::Constant
 -                                          // + span: $DIR/intrinsic_asserts.rs:9:5: 9:59
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn() {assert_mem_uninitialized_valid::<u8>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/issue_101973.inner.ConstProp.diff b/tests/mir-opt/issue_101973.inner.ConstProp.diff
index b377a65b964..d048b9e6513 100644
--- a/tests/mir-opt/issue_101973.inner.ConstProp.diff
+++ b/tests/mir-opt/issue_101973.inner.ConstProp.diff
@@ -16,15 +16,15 @@
       let mut _11: bool;                   // in scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
       let mut _12: u32;                    // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
       let mut _13: bool;                   // in scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
-      scope 1 (inlined imm8) {             // at $DIR/issue_101973.rs:14:5: 14:17
-          debug x => _1;                   // in scope 1 at $DIR/issue_101973.rs:5:13: 5:14
-          let mut _14: u32;                // in scope 1 at $DIR/issue_101973.rs:7:12: 7:27
-          let mut _15: u32;                // in scope 1 at $DIR/issue_101973.rs:7:12: 7:20
+      scope 1 (inlined imm8) {             // at $DIR/issue_101973.rs:15:5: 15:17
+          debug x => _1;                   // in scope 1 at $DIR/issue_101973.rs:6:13: 6:14
+          let mut _14: u32;                // in scope 1 at $DIR/issue_101973.rs:8:12: 8:27
+          let mut _15: u32;                // in scope 1 at $DIR/issue_101973.rs:8:12: 8:20
           scope 2 {
-              debug out => _4;             // in scope 2 at $DIR/issue_101973.rs:6:9: 6:16
+              debug out => _4;             // in scope 2 at $DIR/issue_101973.rs:7:9: 7:16
           }
       }
-      scope 3 (inlined core::num::<impl u32>::rotate_right) { // at $DIR/issue_101973.rs:14:18: 14:58
+      scope 3 (inlined core::num::<impl u32>::rotate_right) { // at $DIR/issue_101973.rs:15:18: 15:58
           debug self => _4;                // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
           debug n => _6;                   // in scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
       }
@@ -33,13 +33,13 @@
           StorageLive(_2);                 // scope 0 at $DIR/issue_101973.rs:+1:5: +1:65
           StorageLive(_3);                 // scope 0 at $DIR/issue_101973.rs:+1:5: +1:58
           StorageLive(_4);                 // scope 0 at $DIR/issue_101973.rs:+1:5: +1:17
-          StorageLive(_14);                // scope 2 at $DIR/issue_101973.rs:7:12: 7:27
-          StorageLive(_15);                // scope 2 at $DIR/issue_101973.rs:7:12: 7:20
-          _15 = Shr(_1, const 0_i32);      // scope 2 at $DIR/issue_101973.rs:7:12: 7:20
-          _14 = BitAnd(move _15, const 255_u32); // scope 2 at $DIR/issue_101973.rs:7:12: 7:27
-          StorageDead(_15);                // scope 2 at $DIR/issue_101973.rs:7:26: 7:27
-          _4 = BitOr(const 0_u32, move _14); // scope 2 at $DIR/issue_101973.rs:7:5: 7:27
-          StorageDead(_14);                // scope 2 at $DIR/issue_101973.rs:7:26: 7:27
+          StorageLive(_14);                // scope 2 at $DIR/issue_101973.rs:8:12: 8:27
+          StorageLive(_15);                // scope 2 at $DIR/issue_101973.rs:8:12: 8:20
+          _15 = Shr(_1, const 0_i32);      // scope 2 at $DIR/issue_101973.rs:8:12: 8:20
+          _14 = BitAnd(move _15, const 255_u32); // scope 2 at $DIR/issue_101973.rs:8:12: 8:27
+          StorageDead(_15);                // scope 2 at $DIR/issue_101973.rs:8:26: 8:27
+          _4 = BitOr(const 0_u32, move _14); // scope 2 at $DIR/issue_101973.rs:8:5: 8:27
+          StorageDead(_14);                // scope 2 at $DIR/issue_101973.rs:8:26: 8:27
           StorageLive(_6);                 // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
           StorageLive(_7);                 // scope 0 at $DIR/issue_101973.rs:+1:31: +1:52
           StorageLive(_8);                 // scope 0 at $DIR/issue_101973.rs:+1:32: +1:45
@@ -66,7 +66,7 @@
       bb2: {
           _6 = Shl(move _7, const 1_i32);  // scope 0 at $DIR/issue_101973.rs:+1:31: +1:57
           StorageDead(_7);                 // scope 0 at $DIR/issue_101973.rs:+1:56: +1:57
-          _3 = rotate_right::<u32>(_4, _6) -> bb3; // scope 3 at $SRC_DIR/core/src/num/uint_macros.rs:LL:COL
+          _3 = rotate_right::<u32>(_4, _6) -> [return: bb3, unwind unreachable]; // scope 3 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: extern "rust-intrinsic" fn(u32, u32) -> u32 {rotate_right::<u32>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/issue_101973.rs b/tests/mir-opt/issue_101973.rs
index 216659a235e..da388f14918 100644
--- a/tests/mir-opt/issue_101973.rs
+++ b/tests/mir-opt/issue_101973.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // compile-flags: -O -C debug-assertions=on
 // This needs inlining followed by ConstProp to reproduce, so we cannot use "unit-test".
 
diff --git a/tests/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir b/tests/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir
index b0d5b291b6c..ccaa508c13b 100644
--- a/tests/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir
+++ b/tests/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir
@@ -19,7 +19,7 @@ fn main() -> () {
     }
 
     bb1: {
-        falseUnwind -> [real: bb2, cleanup: bb5]; // scope 1 at $DIR/issue_38669.rs:+2:5: +7:6
+        falseUnwind -> [real: bb2, unwind: bb5]; // scope 1 at $DIR/issue_38669.rs:+2:5: +7:6
     }
 
     bb2: {
diff --git a/tests/mir-opt/issue_41110.main.ElaborateDrops.diff b/tests/mir-opt/issue_41110.main.ElaborateDrops.diff
index 7ac75b51a37..ac252024928 100644
--- a/tests/mir-opt/issue_41110.main.ElaborateDrops.diff
+++ b/tests/mir-opt/issue_41110.main.ElaborateDrops.diff
@@ -46,17 +46,17 @@
       }
   
       bb3 (cleanup): {
--         drop(_3) -> bb5;                 // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
+-         drop(_3) -> [return: bb5, unwind terminate]; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
 +         goto -> bb5;                     // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
       }
   
       bb4 (cleanup): {
--         drop(_4) -> bb5;                 // scope 0 at $DIR/issue_41110.rs:+1:26: +1:27
+-         drop(_4) -> [return: bb5, unwind terminate]; // scope 0 at $DIR/issue_41110.rs:+1:26: +1:27
 +         goto -> bb5;                     // scope 0 at $DIR/issue_41110.rs:+1:26: +1:27
       }
   
       bb5 (cleanup): {
--         drop(_2) -> bb6;                 // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
+-         drop(_2) -> [return: bb6, unwind terminate]; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
 +         goto -> bb8;                     // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
       }
   
@@ -65,7 +65,7 @@
 +     }
 + 
 +     bb7 (cleanup): {
-+         drop(_2) -> bb6;                 // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
++         drop(_2) -> [return: bb6, unwind terminate]; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
 +     }
 + 
 +     bb8 (cleanup): {
diff --git a/tests/mir-opt/issue_41110.test.ElaborateDrops.diff b/tests/mir-opt/issue_41110.test.ElaborateDrops.diff
index 3dd1a9bbab5..a4a07ad1243 100644
--- a/tests/mir-opt/issue_41110.test.ElaborateDrops.diff
+++ b/tests/mir-opt/issue_41110.test.ElaborateDrops.diff
@@ -50,7 +50,7 @@
   
       bb3 (cleanup): {
           _2 = move _5;                    // scope 2 at $DIR/issue_41110.rs:+4:5: +4:6
-          drop(_5) -> bb8;                 // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
+          drop(_5) -> [return: bb8, unwind terminate]; // scope 2 at $DIR/issue_41110.rs:+4:9: +4:10
       }
   
       bb4: {
@@ -72,18 +72,18 @@
       }
   
       bb7 (cleanup): {
--         drop(_4) -> bb8;                 // scope 2 at $DIR/issue_41110.rs:+3:11: +3:12
+-         drop(_4) -> [return: bb8, unwind terminate]; // scope 2 at $DIR/issue_41110.rs:+3:11: +3:12
 +         goto -> bb8;                     // scope 2 at $DIR/issue_41110.rs:+3:11: +3:12
       }
   
       bb8 (cleanup): {
--         drop(_2) -> bb9;                 // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2
+-         drop(_2) -> [return: bb9, unwind terminate]; // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2
 +         goto -> bb9;                     // scope 1 at $DIR/issue_41110.rs:+5:1: +5:2
       }
   
       bb9 (cleanup): {
--         drop(_1) -> bb10;                // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
-+         goto -> bb12;                    // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
+-         drop(_1) -> [return: bb10, unwind terminate]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
++         goto -> bb13;                    // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
       }
   
       bb10 (cleanup): {
@@ -91,11 +91,15 @@
 +     }
 + 
 +     bb11 (cleanup): {
-+         drop(_1) -> bb10;                // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
++         unreachable;                     // scope 0 at $DIR/issue_41110.rs:+0:1: +5:2
 +     }
 + 
 +     bb12 (cleanup): {
-+         switchInt(_6) -> [0: bb10, otherwise: bb11]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
++         drop(_1) -> [return: bb10, unwind terminate]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
++     }
++ 
++     bb13 (cleanup): {
++         switchInt(_6) -> [0: bb10, otherwise: bb12]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
       }
   }
   
diff --git a/tests/mir-opt/issue_41888.main.ElaborateDrops.diff b/tests/mir-opt/issue_41888.main.ElaborateDrops.diff
index 4e38659a90b..d98f75e7502 100644
--- a/tests/mir-opt/issue_41888.main.ElaborateDrops.diff
+++ b/tests/mir-opt/issue_41888.main.ElaborateDrops.diff
@@ -58,7 +58,7 @@
   
       bb4 (cleanup): {
           _1 = move _3;                    // scope 1 at $DIR/issue_41888.rs:+3:9: +3:10
-          drop(_3) -> bb11;                // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
+          drop(_3) -> [return: bb11, unwind terminate]; // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
       }
   
       bb5: {
@@ -89,7 +89,7 @@
       bb9: {
           StorageDead(_2);                 // scope 1 at $DIR/issue_41888.rs:+8:5: +8:6
 -         drop(_1) -> bb10;                // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
-+         goto -> bb18;                    // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++         goto -> bb19;                    // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
       }
   
       bb10: {
@@ -101,7 +101,7 @@
       }
   
       bb11 (cleanup): {
--         drop(_1) -> bb12;                // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
+-         drop(_1) -> [return: bb12, unwind terminate]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +         goto -> bb12;                    // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
       }
   
@@ -109,39 +109,43 @@
           resume;                          // scope 0 at $DIR/issue_41888.rs:+0:1: +9:2
 +     }
 + 
-+     bb13: {
++     bb13 (cleanup): {
++         unreachable;                     // scope 0 at $DIR/issue_41888.rs:+0:1: +9:2
++     }
++ 
++     bb14: {
 +         _7 = const false;                // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +         goto -> bb10;                    // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +     }
 + 
-+     bb14 (cleanup): {
++     bb15 (cleanup): {
 +         goto -> bb12;                    // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +     }
 + 
-+     bb15: {
-+         drop(_1) -> [return: bb13, unwind: bb12]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++     bb16: {
++         drop(_1) -> [return: bb14, unwind: bb12]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +     }
 + 
-+     bb16 (cleanup): {
-+         drop(_1) -> bb12;                // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++     bb17 (cleanup): {
++         drop(_1) -> [return: bb12, unwind terminate]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +     }
 + 
-+     bb17: {
++     bb18: {
 +         _10 = discriminant(_1);          // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
-+         switchInt(move _10) -> [0: bb13, otherwise: bb15]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++         switchInt(move _10) -> [0: bb14, otherwise: bb16]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +     }
 + 
-+     bb18: {
-+         switchInt(_7) -> [0: bb13, otherwise: bb17]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++     bb19: {
++         switchInt(_7) -> [0: bb14, otherwise: bb18]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +     }
 + 
-+     bb19 (cleanup): {
++     bb20 (cleanup): {
 +         _11 = discriminant(_1);          // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
-+         switchInt(move _11) -> [0: bb14, otherwise: bb16]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++         switchInt(move _11) -> [0: bb15, otherwise: bb17]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
 +     }
 + 
-+     bb20 (cleanup): {
-+         switchInt(_7) -> [0: bb12, otherwise: bb19]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
++     bb21 (cleanup): {
++         switchInt(_7) -> [0: bb12, otherwise: bb20]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
       }
   }
   
diff --git a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.mir b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.mir
index 22b34975d66..8ed9101500e 100644
--- a/tests/mir-opt/issue_62289.test.ElaborateDrops.before.mir
+++ b/tests/mir-opt/issue_62289.test.ElaborateDrops.before.mir
@@ -109,11 +109,11 @@ fn test() -> Option<Box<u32>> {
     }
 
     bb11 (cleanup): {
-        drop(_1) -> bb13;                // scope 0 at $DIR/issue_62289.rs:+4:5: +4:6
+        drop(_1) -> [return: bb13, unwind terminate]; // scope 0 at $DIR/issue_62289.rs:+4:5: +4:6
     }
 
     bb12 (cleanup): {
-        drop(_5) -> bb13;                // scope 0 at $DIR/issue_62289.rs:+3:23: +3:24
+        drop(_5) -> [return: bb13, unwind terminate]; // scope 0 at $DIR/issue_62289.rs:+3:23: +3:24
     }
 
     bb13 (cleanup): {
diff --git a/tests/mir-opt/issue_76432.rs b/tests/mir-opt/issue_76432.rs
index fbbfd4ceb11..76bb11aae3d 100644
--- a/tests/mir-opt/issue_76432.rs
+++ b/tests/mir-opt/issue_76432.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // compile-flags: -Zmir-enable-passes=-NormalizeArrayLen
 // Check that we do not insert StorageDead at each target if StorageDead was never seen
 
diff --git a/tests/mir-opt/issue_91633.bar.built.after.mir b/tests/mir-opt/issue_91633.bar.built.after.mir
index 760e5a8f90a..88a383015b0 100644
--- a/tests/mir-opt/issue_91633.bar.built.after.mir
+++ b/tests/mir-opt/issue_91633.bar.built.after.mir
@@ -31,7 +31,7 @@ fn bar(_1: Box<[T]>) -> () {
     }
 
     bb3 (cleanup): {
-        drop(_1) -> bb4;                 // scope 0 at $DIR/issue_91633.rs:+5:2: +5:3
+        drop(_1) -> [return: bb4, unwind terminate]; // scope 0 at $DIR/issue_91633.rs:+5:2: +5:3
     }
 
     bb4 (cleanup): {
diff --git a/tests/mir-opt/issue_91633.foo.built.after.mir b/tests/mir-opt/issue_91633.foo.built.after.mir
index 4e3dd365e92..569135803ea 100644
--- a/tests/mir-opt/issue_91633.foo.built.after.mir
+++ b/tests/mir-opt/issue_91633.foo.built.after.mir
@@ -48,7 +48,7 @@ fn foo(_1: Box<[T]>) -> T {
     }
 
     bb5 (cleanup): {
-        drop(_1) -> bb6;                 // scope 0 at $DIR/issue_91633.rs:+4:2: +4:3
+        drop(_1) -> [return: bb6, unwind terminate]; // scope 0 at $DIR/issue_91633.rs:+4:2: +4:3
     }
 
     bb6 (cleanup): {
diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
index 6e28fb61b6b..42b60532690 100644
--- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
+++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
@@ -5,7 +5,7 @@ fn num_to_digit(_1: char) -> u32 {
     let mut _0: u32;                     // return place in scope 0 at $DIR/issue_59352.rs:+0:35: +0:38
     let mut _2: std::option::Option<u32>; // in scope 0 at $DIR/issue_59352.rs:+2:26: +2:41
     let mut _3: u32;                     // in scope 0 at $DIR/issue_59352.rs:+2:12: +2:23
-    scope 1 (inlined char::methods::<impl char>::is_digit) { // at $DIR/issue_59352.rs:14:12: 14:23
+    scope 1 (inlined char::methods::<impl char>::is_digit) { // at $DIR/issue_59352.rs:15:12: 15:23
         debug self => _1;                // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
         debug radix => _3;               // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
         let mut _4: &std::option::Option<u32>; // in scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
@@ -15,7 +15,7 @@ fn num_to_digit(_1: char) -> u32 {
             let mut _6: isize;           // in scope 2 at $SRC_DIR/core/src/option.rs:LL:COL
         }
     }
-    scope 3 (inlined #[track_caller] Option::<u32>::unwrap) { // at $DIR/issue_59352.rs:14:42: 14:50
+    scope 3 (inlined #[track_caller] Option::<u32>::unwrap) { // at $DIR/issue_59352.rs:15:42: 15:50
         debug self => _2;                // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
         let mut _7: isize;               // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
         let mut _8: !;                   // in scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
@@ -38,7 +38,7 @@ fn num_to_digit(_1: char) -> u32 {
         StorageLive(_2);                 // scope 0 at $DIR/issue_59352.rs:+2:26: +2:41
         _2 = char::methods::<impl char>::to_digit(_1, const 8_u32) -> bb2; // scope 0 at $DIR/issue_59352.rs:+2:26: +2:41
                                          // mir::Constant
-                                         // + span: $DIR/issue_59352.rs:14:30: 14:38
+                                         // + span: $DIR/issue_59352.rs:15:30: 15:38
                                          // + literal: Const { ty: fn(char, u32) -> Option<u32> {char::methods::<impl char>::to_digit}, val: Value(<ZST>) }
     }
 
diff --git a/tests/mir-opt/issues/issue_59352.rs b/tests/mir-opt/issues/issue_59352.rs
index 1e0045555ab..92011bd6588 100644
--- a/tests/mir-opt/issues/issue_59352.rs
+++ b/tests/mir-opt/issues/issue_59352.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // This test is a mirror of codegen/issue-59352.rs.
 // The LLVM inliner doesn't inline `char::method::is_digit()` and so it doesn't recognize this case
 // as effectively `if x.is_some() { x.unwrap() } else { 0 }`.
diff --git a/tests/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir b/tests/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir
index 4ee2dae49b3..43d00b29e74 100644
--- a/tests/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir
+++ b/tests/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir
@@ -35,7 +35,7 @@ fn main() -> () {
     }
 
     bb3: {
-        falseUnwind -> [real: bb4, cleanup: bb5]; // scope 0 at $DIR/loop_test.rs:+7:5: +10:6
+        falseUnwind -> [real: bb4, unwind: bb5]; // scope 0 at $DIR/loop_test.rs:+7:5: +10:6
     }
 
     bb4: {
diff --git a/tests/mir-opt/lower_array_len.rs b/tests/mir-opt/lower_array_len.rs
index 972d46cb8e2..e1bb51f2d1d 100644
--- a/tests/mir-opt/lower_array_len.rs
+++ b/tests/mir-opt/lower_array_len.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: NormalizeArrayLen
 // compile-flags: -Zmir-enable-passes=+LowerSliceLenCalls
 
diff --git a/tests/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff
index 3389db733b9..dd742d87a29 100644
--- a/tests/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.align_of.LowerIntrinsics.diff
@@ -5,7 +5,7 @@
       let mut _0: usize;                   // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:25: +0:30
   
       bb0: {
--         _0 = std::intrinsics::min_align_of::<T>() -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:42
+-         _0 = std::intrinsics::min_align_of::<T>() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:42
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:21:5: 21:40
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::min_align_of::<T>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff
index 5c5a9e90a9d..935eccfc6f4 100644
--- a/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.assume.LowerIntrinsics.diff
@@ -9,7 +9,7 @@
   
       bb0: {
           StorageLive(_1);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38
--         _1 = std::intrinsics::assume(const true) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38
+-         _1 = std::intrinsics::assume(const true) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+2:9: +2:38
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:105:9: 105:32
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(bool) {std::intrinsics::assume}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
index 87960521bb4..1f03b7b0baf 100644
--- a/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.diff
@@ -29,7 +29,7 @@
           StorageLive(_4);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:42: +1:44
           _4 = &_1;                        // scope 0 at $DIR/lower_intrinsics.rs:+1:42: +1:44
           _3 = &(*_4);                     // scope 0 at $DIR/lower_intrinsics.rs:+1:42: +1:44
--         _2 = discriminant_value::<T>(move _3) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45
+-         _2 = discriminant_value::<T>(move _3) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:45
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:82:5: 82:41
 -                                          // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a T) -> <T as DiscriminantKind>::Discriminant {discriminant_value::<T>}, val: Value(<ZST>) }
@@ -50,7 +50,7 @@
                                            // + literal: Const { ty: &i32, val: Unevaluated(discriminant, [T], Some(promoted[2])) }
           _7 = &(*_19);                    // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44
           _6 = &(*_7);                     // scope 0 at $DIR/lower_intrinsics.rs:+2:42: +2:44
--         _5 = discriminant_value::<i32>(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45
+-         _5 = discriminant_value::<i32>(move _6) -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+2:5: +2:45
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:83:5: 83:41
 -                                          // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a i32) -> <i32 as DiscriminantKind>::Discriminant {discriminant_value::<i32>}, val: Value(<ZST>) }
@@ -71,7 +71,7 @@
                                            // + literal: Const { ty: &(), val: Unevaluated(discriminant, [T], Some(promoted[1])) }
           _11 = &(*_18);                   // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45
           _10 = &(*_11);                   // scope 0 at $DIR/lower_intrinsics.rs:+3:42: +3:45
--         _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46
+-         _9 = discriminant_value::<()>(move _10) -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+3:5: +3:46
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:84:5: 84:41
 -                                          // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a ()) -> <() as DiscriminantKind>::Discriminant {discriminant_value::<()>}, val: Value(<ZST>) }
@@ -92,7 +92,7 @@
                                            // + literal: Const { ty: &E, val: Unevaluated(discriminant, [T], Some(promoted[0])) }
           _15 = &(*_17);                   // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47
           _14 = &(*_15);                   // scope 0 at $DIR/lower_intrinsics.rs:+4:42: +4:47
--         _13 = discriminant_value::<E>(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48
+-         _13 = discriminant_value::<E>(move _14) -> [return: bb4, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+4:5: +4:48
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:85:5: 85:41
 -                                          // + literal: Const { ty: for<'a> extern "rust-intrinsic" fn(&'a E) -> <E as DiscriminantKind>::Discriminant {discriminant_value::<E>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff
index 15cce7f4a2c..b0c32e4b21a 100644
--- a/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.f_copy_nonoverlapping.LowerIntrinsics.diff
@@ -47,7 +47,7 @@
           _9 = _10;                        // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:79
           _8 = move _9 as *mut i32 (PtrToPtr); // scope 3 at $DIR/lower_intrinsics.rs:+4:61: +4:91
           StorageDead(_9);                 // scope 3 at $DIR/lower_intrinsics.rs:+4:90: +4:91
--         _3 = copy_nonoverlapping::<i32>(move _4, move _8, const 0_usize) -> bb1; // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95
+-         _3 = copy_nonoverlapping::<i32>(move _4, move _8, const 0_usize) -> [return: bb1, unwind unreachable]; // scope 3 at $DIR/lower_intrinsics.rs:+4:9: +4:95
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:98:9: 98:28
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const i32, *mut i32, usize) {copy_nonoverlapping::<i32>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff
index 4cbbc02c943..bfb000ccdb5 100644
--- a/tests/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.forget.LowerIntrinsics.diff
@@ -9,7 +9,7 @@
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:30: +1:31
           _2 = move _1;                    // scope 0 at $DIR/lower_intrinsics.rs:+1:30: +1:31
--         _0 = std::intrinsics::forget::<T>(move _2) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:32
+-         _0 = std::intrinsics::forget::<T>(move _2) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:32
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:26:5: 26:29
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(T) {std::intrinsics::forget::<T>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff
index d8cd5f59a35..64d82907c7e 100644
--- a/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.non_const.LowerIntrinsics.diff
@@ -17,7 +17,7 @@
                                            // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}, val: Value(<ZST>) }
           StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:14
           _2 = _1;                         // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:14
--         _0 = move _2() -> bb1;           // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:16
+-         _0 = move _2() -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:16
 +         _0 = SizeOf(T);                  // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:16
 +         goto -> bb1;                     // scope 1 at $DIR/lower_intrinsics.rs:+3:5: +3:16
       }
diff --git a/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.diff
index c563703b250..93863fca344 100644
--- a/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.option_payload.LowerIntrinsics.diff
@@ -22,7 +22,7 @@
           StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:13: +2:15
           StorageLive(_4);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:55: +2:56
           _4 = &raw const (*_1);           // scope 1 at $DIR/lower_intrinsics.rs:+2:55: +2:56
--         _3 = option_payload_ptr::<usize>(move _4) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+2:18: +2:57
+-         _3 = option_payload_ptr::<usize>(move _4) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+2:18: +2:57
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:132:18: 132:54
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const Option<usize>) -> *const usize {option_payload_ptr::<usize>}, val: Value(<ZST>) }
@@ -35,7 +35,7 @@
           StorageLive(_5);                 // scope 2 at $DIR/lower_intrinsics.rs:+3:13: +3:15
           StorageLive(_6);                 // scope 2 at $DIR/lower_intrinsics.rs:+3:55: +3:56
           _6 = &raw const (*_2);           // scope 2 at $DIR/lower_intrinsics.rs:+3:55: +3:56
--         _5 = option_payload_ptr::<String>(move _6) -> bb2; // scope 2 at $DIR/lower_intrinsics.rs:+3:18: +3:57
+-         _5 = option_payload_ptr::<String>(move _6) -> [return: bb2, unwind unreachable]; // scope 2 at $DIR/lower_intrinsics.rs:+3:18: +3:57
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:133:18: 133:54
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const Option<String>) -> *const String {option_payload_ptr::<String>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff
index f2f676843b2..f816678b4b3 100644
--- a/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.read_via_copy_primitive.LowerIntrinsics.diff
@@ -11,7 +11,7 @@
       bb0: {
           StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:46: +1:47
           _2 = &raw const (*_1);           // scope 1 at $DIR/lower_intrinsics.rs:+1:46: +1:47
--         _0 = read_via_copy::<i32>(move _2) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
+-         _0 = read_via_copy::<i32>(move _2) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:118:14: 118:45
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const i32) -> i32 {read_via_copy::<i32>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff
index 3ad21283fa4..f3416418922 100644
--- a/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.read_via_copy_uninhabited.LowerIntrinsics.diff
@@ -11,7 +11,7 @@
       bb0: {
           StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:46: +1:47
           _2 = &raw const (*_1);           // scope 1 at $DIR/lower_intrinsics.rs:+1:46: +1:47
--         _0 = read_via_copy::<Never>(move _2); // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
+-         _0 = read_via_copy::<Never>(move _2) -> unwind unreachable; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:48
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:123:14: 123:45
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(*const Never) -> Never {read_via_copy::<Never>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/lower_intrinsics.size_of.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.size_of.LowerIntrinsics.diff
index cf0ab73a5d4..27e8accea8b 100644
--- a/tests/mir-opt/lower_intrinsics.size_of.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.size_of.LowerIntrinsics.diff
@@ -5,7 +5,7 @@
       let mut _0: usize;                   // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:24: +0:29
   
       bb0: {
--         _0 = std::intrinsics::size_of::<T>() -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:37
+-         _0 = std::intrinsics::size_of::<T>() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:37
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:16:5: 16:35
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn() -> usize {std::intrinsics::size_of::<T>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.diff
index 814368ec021..1b3b7685185 100644
--- a/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.transmute_inhabited.LowerIntrinsics.diff
@@ -11,7 +11,7 @@
       bb0: {
           StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:34: +1:35
           _2 = _1;                         // scope 1 at $DIR/lower_intrinsics.rs:+1:34: +1:35
--         _0 = transmute::<std::cmp::Ordering, i8>(move _2) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:36
+-         _0 = transmute::<std::cmp::Ordering, i8>(move _2) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:36
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:43:14: 43:33
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(std::cmp::Ordering) -> i8 {transmute::<std::cmp::Ordering, i8>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.diff
index 5440c7a4c8e..c6a7d2287e7 100644
--- a/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.transmute_ref_dst.LowerIntrinsics.diff
@@ -11,7 +11,7 @@
       bb0: {
           StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:34: +1:35
           _2 = _1;                         // scope 1 at $DIR/lower_intrinsics.rs:+1:34: +1:35
--         _0 = transmute::<&T, *const T>(move _2) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:36
+-         _0 = transmute::<&T, *const T>(move _2) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:36
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:53:14: 53:33
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(&T) -> *const T {transmute::<&T, *const T>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff
index 43ddccc1ef7..8735a750060 100644
--- a/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.transmute_to_box_uninhabited.LowerIntrinsics.diff
@@ -13,7 +13,7 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
           StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
--         _2 = transmute::<usize, Box<Never>>(const 1_usize) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
+-         _2 = transmute::<usize, Box<Never>>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:70:25: 70:44
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize) -> Box<Never> {transmute::<usize, Box<Never>>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff
index bf529a9ca67..a772132770c 100644
--- a/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.transmute_to_mut_uninhabited.LowerIntrinsics.diff
@@ -13,7 +13,7 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
           StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
--         _2 = transmute::<usize, &mut Never>(const 1_usize) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
+-         _2 = transmute::<usize, &mut Never>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:25: +1:52
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:64:25: 64:44
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize) -> &mut Never {transmute::<usize, &mut Never>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff
index 4940a99021f..c4d53d4e8c7 100644
--- a/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.transmute_to_ref_uninhabited.LowerIntrinsics.diff
@@ -13,7 +13,7 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+0:51: +3:2
           StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:9: +1:10
--         _2 = transmute::<usize, &Never>(const 1_usize) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
+-         _2 = transmute::<usize, &Never>(const 1_usize) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:21: +1:48
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:58:21: 58:40
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(usize) -> &Never {transmute::<usize, &Never>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.diff
index f3a12b9ba5f..f0b76127dd5 100644
--- a/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.transmute_uninhabited.LowerIntrinsics.diff
@@ -11,7 +11,7 @@
       bb0: {
           StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:47: +1:48
           _2 = _1;                         // scope 1 at $DIR/lower_intrinsics.rs:+1:47: +1:48
--         _0 = transmute::<(), Never>(move _2); // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:49
+-         _0 = transmute::<(), Never>(move _2) -> unwind unreachable; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:49
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:48:14: 48:46
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn(()) -> Never {transmute::<(), Never>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
index 6f17d44516d..c0cc698c481 100644
--- a/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.unreachable.LowerIntrinsics.diff
@@ -12,7 +12,7 @@
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:47
           StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
--         _3 = std::intrinsics::unreachable(); // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
+-         _3 = std::intrinsics::unreachable() -> unwind unreachable; // scope 1 at $DIR/lower_intrinsics.rs:+1:14: +1:45
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:31:14: 31:43
 -                                          // + literal: Const { ty: unsafe extern "rust-intrinsic" fn() -> ! {std::intrinsics::unreachable}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff
index 3b9a41249a4..fb12d3dfa6e 100644
--- a/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.with_overflow.LowerIntrinsics.diff
@@ -30,7 +30,7 @@
           _4 = _1;                         // scope 0 at $DIR/lower_intrinsics.rs:+1:50: +1:51
           StorageLive(_5);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:53: +1:54
           _5 = _2;                         // scope 0 at $DIR/lower_intrinsics.rs:+1:53: +1:54
--         _3 = add_with_overflow::<i32>(move _4, move _5) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:55
+-         _3 = add_with_overflow::<i32>(move _4, move _5) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:55
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:111:14: 111:49
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> (i32, bool) {add_with_overflow::<i32>}, val: Value(<ZST>) }
@@ -46,7 +46,7 @@
           _7 = _1;                         // scope 1 at $DIR/lower_intrinsics.rs:+2:50: +2:51
           StorageLive(_8);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:53: +2:54
           _8 = _2;                         // scope 1 at $DIR/lower_intrinsics.rs:+2:53: +2:54
--         _6 = sub_with_overflow::<i32>(move _7, move _8) -> bb2; // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:55
+-         _6 = sub_with_overflow::<i32>(move _7, move _8) -> [return: bb2, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:55
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:112:14: 112:49
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> (i32, bool) {sub_with_overflow::<i32>}, val: Value(<ZST>) }
@@ -62,7 +62,7 @@
           _10 = _1;                        // scope 2 at $DIR/lower_intrinsics.rs:+3:50: +3:51
           StorageLive(_11);                // scope 2 at $DIR/lower_intrinsics.rs:+3:53: +3:54
           _11 = _2;                        // scope 2 at $DIR/lower_intrinsics.rs:+3:53: +3:54
--         _9 = mul_with_overflow::<i32>(move _10, move _11) -> bb3; // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:55
+-         _9 = mul_with_overflow::<i32>(move _10, move _11) -> [return: bb3, unwind unreachable]; // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:55
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:113:14: 113:49
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> (i32, bool) {mul_with_overflow::<i32>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff b/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff
index 22ef75fd804..0bfb34acac2 100644
--- a/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff
+++ b/tests/mir-opt/lower_intrinsics.wrapping.LowerIntrinsics.diff
@@ -30,7 +30,7 @@
           _4 = _1;                         // scope 0 at $DIR/lower_intrinsics.rs:+1:45: +1:46
           StorageLive(_5);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:48: +1:49
           _5 = _2;                         // scope 0 at $DIR/lower_intrinsics.rs:+1:48: +1:49
--         _3 = wrapping_add::<i32>(move _4, move _5) -> bb1; // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:50
+-         _3 = wrapping_add::<i32>(move _4, move _5) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lower_intrinsics.rs:+1:14: +1:50
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:9:14: 9:44
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> i32 {wrapping_add::<i32>}, val: Value(<ZST>) }
@@ -46,7 +46,7 @@
           _7 = _1;                         // scope 1 at $DIR/lower_intrinsics.rs:+2:45: +2:46
           StorageLive(_8);                 // scope 1 at $DIR/lower_intrinsics.rs:+2:48: +2:49
           _8 = _2;                         // scope 1 at $DIR/lower_intrinsics.rs:+2:48: +2:49
--         _6 = wrapping_sub::<i32>(move _7, move _8) -> bb2; // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:50
+-         _6 = wrapping_sub::<i32>(move _7, move _8) -> [return: bb2, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics.rs:+2:14: +2:50
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:10:14: 10:44
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> i32 {wrapping_sub::<i32>}, val: Value(<ZST>) }
@@ -62,7 +62,7 @@
           _10 = _1;                        // scope 2 at $DIR/lower_intrinsics.rs:+3:45: +3:46
           StorageLive(_11);                // scope 2 at $DIR/lower_intrinsics.rs:+3:48: +3:49
           _11 = _2;                        // scope 2 at $DIR/lower_intrinsics.rs:+3:48: +3:49
--         _9 = wrapping_mul::<i32>(move _10, move _11) -> bb3; // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:50
+-         _9 = wrapping_mul::<i32>(move _10, move _11) -> [return: bb3, unwind unreachable]; // scope 2 at $DIR/lower_intrinsics.rs:+3:14: +3:50
 -                                          // mir::Constant
 -                                          // + span: $DIR/lower_intrinsics.rs:11:14: 11:44
 -                                          // + literal: Const { ty: extern "rust-intrinsic" fn(i32, i32) -> i32 {wrapping_mul::<i32>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir b/tests/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir
index adfc6b2731c..4f5df133181 100644
--- a/tests/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir
+++ b/tests/mir-opt/lower_intrinsics_e2e.f_u64.PreCodegen.after.mir
@@ -12,7 +12,7 @@ fn f_u64() -> () {
 
     bb0: {
         StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics_e2e.rs:+1:5: +1:21
-        _2 = f_non_zst::<u64>(const 0_u64) -> bb1; // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21
+        _2 = f_non_zst::<u64>(const 0_u64) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics_e2e.rs:23:9: 23:21
                                          // mir::Constant
                                          // + span: $DIR/lower_intrinsics_e2e.rs:23:9: 23:18
                                          // + literal: Const { ty: fn(u64) {f_non_zst::<u64>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/lower_intrinsics_e2e.f_unit.PreCodegen.after.mir b/tests/mir-opt/lower_intrinsics_e2e.f_unit.PreCodegen.after.mir
index 302ca09aac4..8654e80cd7c 100644
--- a/tests/mir-opt/lower_intrinsics_e2e.f_unit.PreCodegen.after.mir
+++ b/tests/mir-opt/lower_intrinsics_e2e.f_unit.PreCodegen.after.mir
@@ -10,7 +10,7 @@ fn f_unit() -> () {
     }
 
     bb0: {
-        _1 = f_zst::<()>(const ()) -> bb1; // scope 1 at $DIR/lower_intrinsics_e2e.rs:21:9: 21:17
+        _1 = f_zst::<()>(const ()) -> [return: bb1, unwind unreachable]; // scope 1 at $DIR/lower_intrinsics_e2e.rs:21:9: 21:17
                                          // mir::Constant
                                          // + span: $DIR/lower_intrinsics_e2e.rs:21:9: 21:14
                                          // + literal: Const { ty: fn(()) {f_zst::<()>}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff b/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff
index 2b0370cf358..67918e62b9c 100644
--- a/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff
+++ b/tests/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff
@@ -22,7 +22,7 @@
           _6 = &(*_2);                     // scope 0 at $DIR/lower_slice_len.rs:+1:16: +1:27
 -         _5 = core::slice::<impl [u8]>::len(move _6) -> bb1; // scope 0 at $DIR/lower_slice_len.rs:+1:16: +1:27
 -                                          // mir::Constant
--                                          // + span: $DIR/lower_slice_len.rs:5:22: 5:25
+-                                          // + span: $DIR/lower_slice_len.rs:6:22: 6:25
 -                                          // + literal: Const { ty: for<'a> fn(&'a [u8]) -> usize {core::slice::<impl [u8]>::len}, val: Value(<ZST>) }
 +         _5 = Len((*_6));                 // scope 0 at $DIR/lower_slice_len.rs:+1:16: +1:27
 +         goto -> bb1;                     // scope 0 at $DIR/lower_slice_len.rs:+1:16: +1:27
diff --git a/tests/mir-opt/lower_slice_len.rs b/tests/mir-opt/lower_slice_len.rs
index 12955aed1fb..9c39c29fc4e 100644
--- a/tests/mir-opt/lower_slice_len.rs
+++ b/tests/mir-opt/lower_slice_len.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: LowerSliceLenCalls
 
 // EMIT_MIR lower_slice_len.bound.LowerSliceLenCalls.diff
diff --git a/tests/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/tests/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
index 84e4d35f908..3081e78f26d 100644
--- a/tests/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
+++ b/tests/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
@@ -243,7 +243,7 @@
       }
   
 -     bb25 (cleanup): {
--         drop(_2) -> bb26;                // scope 0 at $DIR/match_arm_scopes.rs:+5:1: +5:2
+-         drop(_2) -> [return: bb26, unwind terminate]; // scope 0 at $DIR/match_arm_scopes.rs:+5:1: +5:2
 +     bb22 (cleanup): {
 +         goto -> bb27;                    // scope 0 at $DIR/match_arm_scopes.rs:+5:1: +5:2
       }
diff --git a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir
index 0cb34a2f274..950f8758e31 100644
--- a/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir
+++ b/tests/mir-opt/no_spurious_drop_after_call.main.ElaborateDrops.before.mir
@@ -40,7 +40,7 @@ fn main() -> () {
     }
 
     bb3 (cleanup): {
-        drop(_2) -> bb4;                 // scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:34: +1:35
+        drop(_2) -> [return: bb4, unwind terminate]; // scope 0 at $DIR/no_spurious_drop_after_call.rs:+1:34: +1:35
     }
 
     bb4 (cleanup): {
diff --git a/tests/mir-opt/nrvo_simple.rs b/tests/mir-opt/nrvo_simple.rs
index 5786ae62127..525dfe4262a 100644
--- a/tests/mir-opt/nrvo_simple.rs
+++ b/tests/mir-opt/nrvo_simple.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: RenameReturnPlace
 
 // EMIT_MIR nrvo_simple.nrvo.RenameReturnPlace.diff
diff --git a/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir
index 56cb9166c37..81b96e3b631 100644
--- a/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir
+++ b/tests/mir-opt/packed_struct_drop_aligned.main.SimplifyCfg-elaborate-drops.after.mir
@@ -33,7 +33,7 @@ fn main() -> () {
 
     bb1 (cleanup): {
         (_1.0: Aligned) = move _4;       // scope 1 at $DIR/packed_struct_drop_aligned.rs:+2:5: +2:8
-        drop(_1) -> bb3;                 // scope 0 at $DIR/packed_struct_drop_aligned.rs:+3:1: +3:2
+        drop(_1) -> [return: bb3, unwind terminate]; // scope 0 at $DIR/packed_struct_drop_aligned.rs:+3:1: +3:2
     }
 
     bb2: {
diff --git a/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff b/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
index a8dd91efc37..0e8309532c2 100644
--- a/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
+++ b/tests/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
@@ -34,7 +34,7 @@
           _3 = std::ops::Range::<i32> { start: const 0_i32, end: const 10_i32 }; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
           _2 = <std::ops::Range<i32> as IntoIterator>::into_iter(move _3) -> bb1; // scope 1 at $DIR/remove_storage_markers.rs:+2:14: +2:19
                                            // mir::Constant
-                                           // + span: $DIR/remove_storage_markers.rs:10:14: 10:19
+                                           // + span: $DIR/remove_storage_markers.rs:11:14: 11:19
                                            // + literal: Const { ty: fn(std::ops::Range<i32>) -> <std::ops::Range<i32> as IntoIterator>::IntoIter {<std::ops::Range<i32> as IntoIterator>::into_iter}, val: Value(<ZST>) }
       }
   
@@ -54,7 +54,7 @@
           _8 = &mut (*_9);                 // scope 2 at $DIR/remove_storage_markers.rs:+2:14: +2:19
           _7 = <std::ops::Range<i32> as Iterator>::next(move _8) -> bb3; // scope 2 at $DIR/remove_storage_markers.rs:+2:14: +2:19
                                            // mir::Constant
-                                           // + span: $DIR/remove_storage_markers.rs:10:14: 10:19
+                                           // + span: $DIR/remove_storage_markers.rs:11:14: 11:19
                                            // + literal: Const { ty: for<'a> fn(&'a mut std::ops::Range<i32>) -> Option<<std::ops::Range<i32> as Iterator>::Item> {<std::ops::Range<i32> as Iterator>::next}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/remove_storage_markers.rs b/tests/mir-opt/remove_storage_markers.rs
index f00b826911c..480db8ac155 100644
--- a/tests/mir-opt/remove_storage_markers.rs
+++ b/tests/mir-opt/remove_storage_markers.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: RemoveStorageMarkers
 
 // Checks that storage markers are removed at opt-level=0.
diff --git a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
index 2eb2a0980ce..4eef028e1cc 100644
--- a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
+++ b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
@@ -186,11 +186,11 @@ fn main() -> () {
     }
 
     bb7 (cleanup): {
-        drop(_21) -> bb9;                // scope 7 at $DIR/retag.rs:+18:24: +18:25
+        drop(_21) -> [return: bb9, unwind terminate]; // scope 7 at $DIR/retag.rs:+18:24: +18:25
     }
 
     bb8 (cleanup): {
-        drop(_5) -> bb9;                 // scope 1 at $DIR/retag.rs:+3:36: +3:37
+        drop(_5) -> [return: bb9, unwind terminate]; // scope 1 at $DIR/retag.rs:+3:36: +3:37
     }
 
     bb9 (cleanup): {
diff --git a/tests/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff b/tests/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff
index 1e66b1f703e..c61107d25e0 100644
--- a/tests/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff
+++ b/tests/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff
@@ -12,8 +12,8 @@
       }
   
       bb1: {
--         falseUnwind -> [real: bb2, cleanup: bb11]; // scope 0 at $DIR/simplify_cfg.rs:+1:5: +5:6
-+         falseUnwind -> [real: bb2, cleanup: bb6]; // scope 0 at $DIR/simplify_cfg.rs:+1:5: +5:6
+-         falseUnwind -> [real: bb2, unwind: bb11]; // scope 0 at $DIR/simplify_cfg.rs:+1:5: +5:6
++         falseUnwind -> [real: bb2, unwind: bb6]; // scope 0 at $DIR/simplify_cfg.rs:+1:5: +5:6
       }
   
       bb2: {
diff --git a/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff b/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff
index ac79e727013..b473d0fdecd 100644
--- a/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff
+++ b/tests/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff
@@ -16,7 +16,7 @@
       bb1: {
           _2 = noop() -> bb2;              // scope 0 at $DIR/simplify_if.rs:+2:9: +2:15
                                            // mir::Constant
-                                           // + span: $DIR/simplify_if.rs:7:9: 7:13
+                                           // + span: $DIR/simplify_if.rs:8:9: 8:13
                                            // + literal: Const { ty: fn() {noop}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/simplify_if.rs b/tests/mir-opt/simplify_if.rs
index 2d093d9266b..b86f80a8038 100644
--- a/tests/mir-opt/simplify_if.rs
+++ b/tests/mir-opt/simplify_if.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 #[inline(never)]
 fn noop() {}
 
diff --git a/tests/mir-opt/simplify_locals_fixedpoint.rs b/tests/mir-opt/simplify_locals_fixedpoint.rs
index 1fdba6e99e3..7c41e8b7c20 100644
--- a/tests/mir-opt/simplify_locals_fixedpoint.rs
+++ b/tests/mir-opt/simplify_locals_fixedpoint.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // compile-flags: -Zmir-opt-level=1
 
 fn foo<T>() {
diff --git a/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff b/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff
index 0f8866f9c2f..ae2c774f29d 100644
--- a/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff
+++ b/tests/mir-opt/simplify_locals_removes_unused_consts.main.SimplifyLocals-before-const-prop.diff
@@ -56,7 +56,7 @@
 +         StorageDead(_3);                 // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:20: +2:21
 +         _1 = use_zst(move _2) -> bb1;    // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+2:5: +2:22
                                            // mir::Constant
-                                           // + span: $DIR/simplify_locals_removes_unused_consts.rs:15:5: 15:12
+                                           // + span: $DIR/simplify_locals_removes_unused_consts.rs:16:5: 16:12
                                            // + literal: Const { ty: fn(((), ())) {use_zst}, val: Value(<ZST>) }
       }
   
@@ -84,7 +84,7 @@
 +         StorageDead(_7);                 // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:33: +4:34
 +         _5 = use_u8(move _6) -> bb2;     // scope 1 at $DIR/simplify_locals_removes_unused_consts.rs:+4:5: +4:35
                                            // mir::Constant
-                                           // + span: $DIR/simplify_locals_removes_unused_consts.rs:17:5: 17:11
+                                           // + span: $DIR/simplify_locals_removes_unused_consts.rs:18:5: 18:11
                                            // + literal: Const { ty: fn(u8) {use_u8}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/simplify_locals_removes_unused_consts.rs b/tests/mir-opt/simplify_locals_removes_unused_consts.rs
index 7a03a2837ae..983d8004e2e 100644
--- a/tests/mir-opt/simplify_locals_removes_unused_consts.rs
+++ b/tests/mir-opt/simplify_locals_removes_unused_consts.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // unit-test: SimplifyLocals-before-const-prop
 // compile-flags: -C overflow-checks=no
 
diff --git a/tests/mir-opt/simplify_match.main.ConstProp.diff b/tests/mir-opt/simplify_match.main.ConstProp.diff
index b700adfb105..d2b9ac3cc0b 100644
--- a/tests/mir-opt/simplify_match.main.ConstProp.diff
+++ b/tests/mir-opt/simplify_match.main.ConstProp.diff
@@ -22,7 +22,7 @@
       bb2: {
           _0 = noop() -> bb3;              // scope 0 at $DIR/simplify_match.rs:+2:17: +2:23
                                            // mir::Constant
-                                           // + span: $DIR/simplify_match.rs:7:17: 7:21
+                                           // + span: $DIR/simplify_match.rs:8:17: 8:21
                                            // + literal: Const { ty: fn() {noop}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/simplify_match.rs b/tests/mir-opt/simplify_match.rs
index 216203f9ff0..6a2a6f21719 100644
--- a/tests/mir-opt/simplify_match.rs
+++ b/tests/mir-opt/simplify_match.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 #[inline(never)]
 fn noop() {}
 
diff --git a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir
index 3884d29db41..11115c96e23 100644
--- a/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir
+++ b/tests/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir
@@ -24,7 +24,7 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
     bb3 (cleanup): {
         _4 = &raw mut (*_1)[_3];         // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
         _3 = Add(move _3, const 1_usize); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        drop((*_4)) -> bb4;              // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        drop((*_4)) -> [return: bb4, unwind terminate]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     }
 
     bb4 (cleanup): {
diff --git a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff
index f6f2344e82f..579587a430b 100644
--- a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff
+++ b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff
@@ -58,7 +58,7 @@
           StorageLive(_2);                 // scope 0 at $DIR/lifetimes.rs:+2:12: +2:31
           StorageLive(_3);                 // scope 0 at $DIR/lifetimes.rs:+2:15: +2:30
           StorageLive(_4);                 // scope 0 at $DIR/lifetimes.rs:+2:15: +2:30
-          _4 = Box::<u32>::new(const 5_u32) -> bb1; // scope 0 at $DIR/lifetimes.rs:+2:15: +2:30
+          _4 = Box::<u32>::new(const 5_u32) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/lifetimes.rs:+2:15: +2:30
                                            // mir::Constant
                                            // + span: $DIR/lifetimes.rs:19:15: 19:23
                                            // + user_ty: UserType(1)
@@ -113,7 +113,7 @@
           StorageLive(_22);                // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
           _22 = &_8;                       // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
           _21 = &(*_22);                   // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
-          _20 = core::fmt::ArgumentV1::<'_>::new_display::<Box<dyn std::fmt::Display>>(move _21) -> bb3; // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
+          _20 = core::fmt::ArgumentV1::<'_>::new_display::<Box<dyn std::fmt::Display>>(move _21) -> [return: bb3, unwind unreachable]; // scope 4 at $DIR/lifetimes.rs:+10:20: +10:23
                                            // mir::Constant
                                            // + span: $DIR/lifetimes.rs:27:20: 27:23
                                            // + user_ty: UserType(4)
@@ -127,7 +127,7 @@
           StorageLive(_25);                // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
           _25 = &_6;                       // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
           _24 = &(*_25);                   // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
-          _23 = core::fmt::ArgumentV1::<'_>::new_display::<u32>(move _24) -> bb4; // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
+          _23 = core::fmt::ArgumentV1::<'_>::new_display::<u32>(move _24) -> [return: bb4, unwind unreachable]; // scope 4 at $DIR/lifetimes.rs:+10:24: +10:27
                                            // mir::Constant
                                            // + span: $DIR/lifetimes.rs:27:24: 27:27
                                            // + user_ty: UserType(5)
@@ -143,7 +143,7 @@
           _17 = &(*_18);                   // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
           _16 = move _17 as &[core::fmt::ArgumentV1<'_>] (Pointer(Unsize)); // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
           StorageDead(_17);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _11 = Arguments::<'_>::new_v1(move _12, move _16) -> bb5; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _11 = Arguments::<'_>::new_v1(move _12, move _16) -> [return: bb5, unwind unreachable]; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/std/src/macros.rs:LL:COL
                                            // + user_ty: UserType(3)
@@ -153,7 +153,7 @@
       bb5: {
           StorageDead(_16);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
           StorageDead(_12);                // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
-          _10 = _eprint(move _11) -> bb6;  // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
+          _10 = _eprint(move _11) -> [return: bb6, unwind unreachable]; // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
                                            // mir::Constant
                                            // + span: $SRC_DIR/std/src/macros.rs:LL:COL
                                            // + literal: Const { ty: for<'a> fn(Arguments<'a>) {_eprint}, val: Value(<ZST>) }
@@ -170,7 +170,7 @@
           _9 = const ();                   // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
           StorageDead(_9);                 // scope 4 at $SRC_DIR/std/src/macros.rs:LL:COL
           _0 = const ();                   // scope 4 at $DIR/lifetimes.rs:+9:22: +11:6
-          drop(_8) -> bb8;                 // scope 3 at $DIR/lifetimes.rs:+11:5: +11:6
+          drop(_8) -> [return: bb8, unwind unreachable]; // scope 3 at $DIR/lifetimes.rs:+11:5: +11:6
       }
   
       bb7: {
@@ -204,11 +204,11 @@
       }
   
       bb12: {
-          drop(((_5 as Ok).0: std::boxed::Box<dyn std::fmt::Display>)) -> bb10; // scope 1 at $DIR/lifetimes.rs:+12:1: +12:2
+          drop(((_5 as Ok).0: std::boxed::Box<dyn std::fmt::Display>)) -> [return: bb10, unwind unreachable]; // scope 1 at $DIR/lifetimes.rs:+12:1: +12:2
       }
   
       bb13: {
-          drop(_5) -> bb10;                // scope 1 at $DIR/lifetimes.rs:+12:1: +12:2
+          drop(_5) -> [return: bb10, unwind unreachable]; // scope 1 at $DIR/lifetimes.rs:+12:1: +12:2
       }
   }
   
diff --git a/tests/mir-opt/sroa/structs.dropping.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.dropping.ScalarReplacementOfAggregates.diff
index b6439c00a00..d378c260a00 100644
--- a/tests/mir-opt/sroa/structs.dropping.ScalarReplacementOfAggregates.diff
+++ b/tests/mir-opt/sroa/structs.dropping.ScalarReplacementOfAggregates.diff
@@ -23,11 +23,11 @@
           StorageDead(_4);                 // scope 0 at $DIR/structs.rs:+1:29: +1:30
           StorageDead(_3);                 // scope 0 at $DIR/structs.rs:+1:29: +1:30
           _1 = move (_2.1: Tag);           // scope 0 at $DIR/structs.rs:+1:5: +1:32
-          drop(_1) -> bb1;                 // scope 0 at $DIR/structs.rs:+1:32: +1:33
+          drop(_1) -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/structs.rs:+1:32: +1:33
       }
   
       bb1: {
-          drop((_2.0: Tag)) -> bb3;        // scope 0 at $DIR/structs.rs:+1:32: +1:33
+          drop((_2.0: Tag)) -> [return: bb3, unwind unreachable]; // scope 0 at $DIR/structs.rs:+1:32: +1:33
       }
   
       bb2: {
@@ -38,7 +38,7 @@
       }
   
       bb3: {
-          drop((_2.2: Tag)) -> bb2;        // scope 0 at $DIR/structs.rs:+1:32: +1:33
+          drop((_2.2: Tag)) -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/structs.rs:+1:32: +1:33
       }
   }
   
diff --git a/tests/mir-opt/sroa/structs.escaping.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.escaping.ScalarReplacementOfAggregates.diff
index d45823d4bac..3074fcbdf53 100644
--- a/tests/mir-opt/sroa/structs.escaping.ScalarReplacementOfAggregates.diff
+++ b/tests/mir-opt/sroa/structs.escaping.ScalarReplacementOfAggregates.diff
@@ -15,7 +15,7 @@
           StorageLive(_3);                 // scope 0 at $DIR/structs.rs:+1:7: +1:41
           StorageLive(_4);                 // scope 0 at $DIR/structs.rs:+1:8: +1:39
           StorageLive(_5);                 // scope 0 at $DIR/structs.rs:+1:34: +1:37
-          _5 = g() -> bb1;                 // scope 0 at $DIR/structs.rs:+1:34: +1:37
+          _5 = g() -> [return: bb1, unwind unreachable]; // scope 0 at $DIR/structs.rs:+1:34: +1:37
                                            // mir::Constant
                                            // + span: $DIR/structs.rs:78:34: 78:35
                                            // + literal: Const { ty: fn() -> u32 {g}, val: Value(<ZST>) }
@@ -26,7 +26,7 @@
           StorageDead(_5);                 // scope 0 at $DIR/structs.rs:+1:38: +1:39
           _3 = &(_4.0: u32);               // scope 0 at $DIR/structs.rs:+1:7: +1:41
           _2 = &raw const (*_3);           // scope 0 at $DIR/structs.rs:+1:7: +1:41
-          _1 = f(move _2) -> bb2;          // scope 0 at $DIR/structs.rs:+1:5: +1:42
+          _1 = f(move _2) -> [return: bb2, unwind unreachable]; // scope 0 at $DIR/structs.rs:+1:5: +1:42
                                            // mir::Constant
                                            // + span: $DIR/structs.rs:78:5: 78:6
                                            // + literal: Const { ty: fn(*const u32) {f}, val: Value(<ZST>) }
diff --git a/tests/mir-opt/unreachable.main.UnreachablePropagation.diff b/tests/mir-opt/unreachable.main.UnreachablePropagation.diff
index 848bff1d492..323b61346c0 100644
--- a/tests/mir-opt/unreachable.main.UnreachablePropagation.diff
+++ b/tests/mir-opt/unreachable.main.UnreachablePropagation.diff
@@ -21,7 +21,7 @@
           StorageLive(_1);                 // scope 1 at $DIR/unreachable.rs:+1:23: +1:30
           _1 = empty() -> bb1;             // scope 1 at $DIR/unreachable.rs:+1:23: +1:30
                                            // mir::Constant
-                                           // + span: $DIR/unreachable.rs:9:23: 9:28
+                                           // + span: $DIR/unreachable.rs:10:23: 10:28
                                            // + literal: Const { ty: fn() -> Option<Empty> {empty}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/unreachable.rs b/tests/mir-opt/unreachable.rs
index 6098b525b55..97093729dd1 100644
--- a/tests/mir-opt/unreachable.rs
+++ b/tests/mir-opt/unreachable.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 enum Empty {}
 
 fn empty() -> Option<Empty> {
diff --git a/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff b/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff
index fb778470e53..94bc633613b 100644
--- a/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff
+++ b/tests/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff
@@ -23,7 +23,7 @@
           StorageLive(_2);                 // scope 2 at $DIR/unreachable_diverging.rs:+2:25: +2:32
           _2 = empty() -> bb1;             // scope 2 at $DIR/unreachable_diverging.rs:+2:25: +2:32
                                            // mir::Constant
-                                           // + span: $DIR/unreachable_diverging.rs:14:25: 14:30
+                                           // + span: $DIR/unreachable_diverging.rs:15:25: 15:30
                                            // + literal: Const { ty: fn() -> Option<Empty> {empty}, val: Value(<ZST>) }
       }
   
@@ -44,7 +44,7 @@
       bb3: {
           _5 = loop_forever() -> bb5;      // scope 2 at $DIR/unreachable_diverging.rs:+4:13: +4:27
                                            // mir::Constant
-                                           // + span: $DIR/unreachable_diverging.rs:16:13: 16:25
+                                           // + span: $DIR/unreachable_diverging.rs:17:13: 17:25
                                            // + literal: Const { ty: fn() {loop_forever}, val: Value(<ZST>) }
       }
   
diff --git a/tests/mir-opt/unreachable_diverging.rs b/tests/mir-opt/unreachable_diverging.rs
index bbf28efc7dd..24e776148c1 100644
--- a/tests/mir-opt/unreachable_diverging.rs
+++ b/tests/mir-opt/unreachable_diverging.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 pub enum Empty {}
 
 fn empty() -> Option<Empty> {
diff --git a/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir b/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir
index ed9f3bdbdf4..c27a93e91f8 100644
--- a/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir
+++ b/tests/mir-opt/unusual_item_types.core.ptr-drop_in_place.Vec_i32_.AddMovesForPackedDrops.before.mir
@@ -22,7 +22,7 @@ fn std::ptr::drop_in_place(_1: *mut Vec<i32>) -> () {
     }
 
     bb4 (cleanup): {
-        drop(((*_1).0: alloc::raw_vec::RawVec<i32>)) -> bb2; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        drop(((*_1).0: alloc::raw_vec::RawVec<i32>)) -> [return: bb2, unwind terminate]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     }
 
     bb5: {
diff --git a/tests/mir-opt/while_storage.rs b/tests/mir-opt/while_storage.rs
index afd083acb34..d10048dd908 100644
--- a/tests/mir-opt/while_storage.rs
+++ b/tests/mir-opt/while_storage.rs
@@ -1,3 +1,4 @@
+// ignore-wasm32 compiled with panic=abort by default
 // Test that we correctly generate StorageDead statements for while loop
 // conditions on all branches
 
diff --git a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir
index 318119bd477..811789a60c3 100644
--- a/tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir
+++ b/tests/mir-opt/while_storage.while_loop.PreCodegen.after.mir
@@ -14,7 +14,7 @@ fn while_loop(_1: bool) -> () {
         StorageLive(_2);                 // scope 0 at $DIR/while_storage.rs:+1:11: +1:22
         _2 = get_bool(_1) -> bb2;        // scope 0 at $DIR/while_storage.rs:+1:11: +1:22
                                          // mir::Constant
-                                         // + span: $DIR/while_storage.rs:10:11: 10:19
+                                         // + span: $DIR/while_storage.rs:11:11: 11:19
                                          // + literal: Const { ty: fn(bool) -> bool {get_bool}, val: Value(<ZST>) }
     }
 
@@ -26,7 +26,7 @@ fn while_loop(_1: bool) -> () {
         StorageLive(_3);                 // scope 0 at $DIR/while_storage.rs:+2:12: +2:23
         _3 = get_bool(_1) -> bb4;        // scope 0 at $DIR/while_storage.rs:+2:12: +2:23
                                          // mir::Constant
-                                         // + span: $DIR/while_storage.rs:11:12: 11:20
+                                         // + span: $DIR/while_storage.rs:12:12: 12:20
                                          // + literal: Const { ty: fn(bool) -> bool {get_bool}, val: Value(<ZST>) }
     }
 
diff --git a/tests/run-make/coverage-reports/expected_show_coverage.abort.txt b/tests/run-make/coverage-reports/expected_show_coverage.abort.txt
index 00f46f42a07..a71c58d618d 100644
--- a/tests/run-make/coverage-reports/expected_show_coverage.abort.txt
+++ b/tests/run-make/coverage-reports/expected_show_coverage.abort.txt
@@ -32,7 +32,7 @@
    30|       |// Notes:
    31|       |//   1. Compare this program and its coverage results to those of the similar tests
    32|       |//      `panic_unwind.rs` and `try_error_result.rs`.
-   33|       |//   2. This test confirms the coverage generated when a program includes `TerminatorKind::Abort`.
+   33|       |//   2. This test confirms the coverage generated when a program includes `UnwindAction::Terminate`.
    34|       |//   3. The test does not invoke the abort. By executing to a successful completion, the coverage
    35|       |//      results show where the program did and did not execute.
    36|       |//   4. If the program actually aborted, the coverage counters would not be saved (which "works as
diff --git a/tests/run-make/coverage/abort.rs b/tests/run-make/coverage/abort.rs
index 3dac43df8f3..98264bdc1af 100644
--- a/tests/run-make/coverage/abort.rs
+++ b/tests/run-make/coverage/abort.rs
@@ -30,7 +30,7 @@ fn main() -> Result<(), u8> {
 // Notes:
 //   1. Compare this program and its coverage results to those of the similar tests
 //      `panic_unwind.rs` and `try_error_result.rs`.
-//   2. This test confirms the coverage generated when a program includes `TerminatorKind::Abort`.
+//   2. This test confirms the coverage generated when a program includes `UnwindAction::Terminate`.
 //   3. The test does not invoke the abort. By executing to a successful completion, the coverage
 //      results show where the program did and did not execute.
 //   4. If the program actually aborted, the coverage counters would not be saved (which "works as
diff --git a/tests/rustdoc-gui/go-to-collapsed-elem.goml b/tests/rustdoc-gui/go-to-collapsed-elem.goml
index 279048e37c1..ec423125236 100644
--- a/tests/rustdoc-gui/go-to-collapsed-elem.goml
+++ b/tests/rustdoc-gui/go-to-collapsed-elem.goml
@@ -9,13 +9,32 @@ property: ("#implementations-list .implementors-toggle", {"open": "false"})
 click: "//*[@class='sidebar']//a[@href='#method.must_use']"
 assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
 
-// Now we do the same through search result.
-// First we reload the page without the anchor in the URL.
+define-function: ("collapsed-from-search", (), block {
+    // Now we do the same through search result.
+    // First we reload the page without the anchor in the URL.
+    goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+    // Then we collapse the section again...
+    property: ("#implementations-list .implementors-toggle", {"open": "false"})
+    // Then we run the search.
+    write: (".search-input", "foo::must_use")
+    wait-for: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']"
+    click: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']"
+    assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
+})
+
+call-function: ("collapsed-from-search", {})
+
+// Now running the same check but with mobile.
+size: (600, 600)
 goto: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
-// Then we collapse the section again...
+// We check that the implementors block is expanded.
+assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
+// We now collapse the implementors block.
 property: ("#implementations-list .implementors-toggle", {"open": "false"})
-// Then we run the search.
-write: (".search-input", "foo::must_use")
-wait-for: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']"
-click: "//*[@id='search']//a[@href='../test_docs/struct.Foo.html#method.must_use']"
+// First we expand the mobile menu.
+click: ".sidebar-menu-toggle"
+// Then we click on the link to the method to ensure it'll expand the implementors block.
+click: "//*[@class='sidebar shown']//a[@href='#method.must_use']"
 assert-property: ("#implementations-list .implementors-toggle", {"open": "true"})
+
+call-function: ("collapsed-from-search", {})
diff --git a/tests/rustdoc-gui/theme-defaults.goml b/tests/rustdoc-gui/theme-defaults.goml
new file mode 100644
index 00000000000..d5ed536b1a9
--- /dev/null
+++ b/tests/rustdoc-gui/theme-defaults.goml
@@ -0,0 +1,24 @@
+// Ensure that the theme picker always starts with the actual defaults.
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+click: "#settings-menu"
+wait-for: "#theme-system-preference"
+assert: "#theme-system-preference:checked"
+assert: "#preferred-light-theme-light:checked"
+assert: "#preferred-dark-theme-dark:checked"
+assert-false: "#preferred-dark-theme-ayu:checked"
+
+// Test legacy migration from old theme setup without system-preference matching.
+// See https://github.com/rust-lang/rust/pull/77809#issuecomment-707875732
+local-storage: {
+    "rustdoc-preferred-light-theme": null,
+    "rustdoc-preferred-dark-theme": null,
+    "rustdoc-use-system-theme": null,
+    "rustdoc-theme": "ayu"
+}
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+click: "#settings-menu"
+wait-for: "#theme-system-preference"
+assert: "#theme-system-preference:checked"
+assert: "#preferred-light-theme-light:checked"
+assert-false: "#preferred-dark-theme-dark:checked"
+assert: "#preferred-dark-theme-ayu:checked"
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
index 3151c712566..61724c11745 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
@@ -50,7 +50,7 @@ enum DiagnosticOnEnum {
 #[derive(Diagnostic)]
 #[diag(no_crate_example, code = "E0123")]
 #[diag = "E0123"]
-//~^ ERROR `#[diag = ...]` is not a valid attribute
+//~^ ERROR expected parentheses: #[diag(...)]
 struct WrongStructAttrStyle {}
 
 #[derive(Diagnostic)]
@@ -62,8 +62,7 @@ struct InvalidStructAttr {}
 
 #[derive(Diagnostic)]
 #[diag("E0123")]
-//~^ ERROR `#[diag("...")]` is not a valid attribute
-//~^^ ERROR diagnostic slug not specified
+//~^ ERROR diagnostic slug not specified
 struct InvalidLitNestedAttr {}
 
 #[derive(Diagnostic)]
@@ -73,27 +72,25 @@ struct InvalidNestedStructAttr {}
 
 #[derive(Diagnostic)]
 #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
-//~^ ERROR `#[diag(nonsense(...))]` is not a valid attribute
-//~^^ ERROR diagnostic slug not specified
+//~^ ERROR diagnostic slug must be the first argument
+//~| ERROR diagnostic slug not specified
 struct InvalidNestedStructAttr1 {}
 
 #[derive(Diagnostic)]
 #[diag(nonsense = "...", code = "E0123", slug = "foo")]
-//~^ ERROR `#[diag(nonsense = ...)]` is not a valid attribute
-//~| ERROR `#[diag(slug = ...)]` is not a valid attribute
+//~^ ERROR unknown argument
 //~| ERROR diagnostic slug not specified
 struct InvalidNestedStructAttr2 {}
 
 #[derive(Diagnostic)]
 #[diag(nonsense = 4, code = "E0123", slug = "foo")]
-//~^ ERROR `#[diag(nonsense = ...)]` is not a valid attribute
-//~| ERROR `#[diag(slug = ...)]` is not a valid attribute
+//~^ ERROR unknown argument
 //~| ERROR diagnostic slug not specified
 struct InvalidNestedStructAttr3 {}
 
 #[derive(Diagnostic)]
 #[diag(no_crate_example, code = "E0123", slug = "foo")]
-//~^ ERROR `#[diag(slug = ...)]` is not a valid attribute
+//~^ ERROR unknown argument
 struct InvalidNestedStructAttr4 {}
 
 #[derive(Diagnostic)]
@@ -118,7 +115,7 @@ struct CodeSpecifiedTwice {}
 
 #[derive(Diagnostic)]
 #[diag(no_crate_example, no_crate::example, code = "E0456")]
-//~^ ERROR `#[diag(no_crate::example)]` is not a valid attribute
+//~^ ERROR diagnostic slug must be the first argument
 struct SlugSpecifiedTwice {}
 
 #[derive(Diagnostic)]
@@ -232,7 +229,7 @@ struct SuggestWithoutCode {
 #[diag(no_crate_example, code = "E0123")]
 struct SuggestWithBadKey {
     #[suggestion(nonsense = "bar")]
-    //~^ ERROR `#[suggestion(nonsense = ...)]` is not a valid attribute
+    //~^ ERROR invalid nested attribute
     //~| ERROR suggestion without `code = "..."`
     suggestion: (Span, Applicability),
 }
@@ -241,7 +238,7 @@ struct SuggestWithBadKey {
 #[diag(no_crate_example, code = "E0123")]
 struct SuggestWithShorthandMsg {
     #[suggestion(msg = "bar")]
-    //~^ ERROR `#[suggestion(msg = ...)]` is not a valid attribute
+    //~^ ERROR invalid nested attribute
     //~| ERROR suggestion without `code = "..."`
     suggestion: (Span, Applicability),
 }
@@ -530,7 +527,7 @@ struct BoolField {
 #[diag(no_crate_example, code = "E0123")]
 struct LabelWithTrailingPath {
     #[label(no_crate_label, foo)]
-    //~^ ERROR `#[label(foo)]` is not a valid attribute
+    //~^ ERROR a diagnostic slug must be the first argument to the attribute
     span: Span,
 }
 
@@ -538,7 +535,7 @@ struct LabelWithTrailingPath {
 #[diag(no_crate_example, code = "E0123")]
 struct LabelWithTrailingNameValue {
     #[label(no_crate_label, foo = "...")]
-    //~^ ERROR `#[label(foo = ...)]` is not a valid attribute
+    //~^ ERROR invalid nested attribute
     span: Span,
 }
 
@@ -546,7 +543,7 @@ struct LabelWithTrailingNameValue {
 #[diag(no_crate_example, code = "E0123")]
 struct LabelWithTrailingList {
     #[label(no_crate_label, foo("..."))]
-    //~^ ERROR `#[label(foo(...))]` is not a valid attribute
+    //~^ ERROR invalid nested attribute
     span: Span,
 }
 
@@ -643,8 +640,8 @@ struct MissingCodeInSuggestion {
 //~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute
 //~| ERROR cannot find attribute `multipart_suggestion` in this scope
 #[multipart_suggestion()]
-//~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute
-//~| ERROR cannot find attribute `multipart_suggestion` in this scope
+//~^ ERROR cannot find attribute `multipart_suggestion` in this scope
+//~| ERROR unexpected end of input, unexpected token in nested attribute, expected ident
 struct MultipartSuggestion {
     #[multipart_suggestion(no_crate_suggestion)]
     //~^ ERROR `#[multipart_suggestion(...)]` is not a valid attribute
@@ -698,7 +695,7 @@ struct RawIdentDiagnosticArg {
 #[diag(no_crate_example)]
 struct SubdiagnosticBad {
     #[subdiagnostic(bad)]
-    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
+    //~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic`
     note: Note,
 }
 
@@ -714,7 +711,7 @@ struct SubdiagnosticBadStr {
 #[diag(no_crate_example)]
 struct SubdiagnosticBadTwice {
     #[subdiagnostic(bad, bad)]
-    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
+    //~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic`
     note: Note,
 }
 
@@ -722,7 +719,7 @@ struct SubdiagnosticBadTwice {
 #[diag(no_crate_example)]
 struct SubdiagnosticBadLitStr {
     #[subdiagnostic("bad")]
-    //~^ ERROR `#[subdiagnostic(...)]` is not a valid attribute
+    //~^ ERROR `eager` is the only supported nested attribute for `subdiagnostic`
     note: Note,
 }
 
@@ -797,14 +794,15 @@ struct SuggestionsNoItem {
 struct SuggestionsInvalidItem {
     #[suggestion(code(foo))]
     //~^ ERROR `code(...)` must contain only string literals
+    //~| ERROR unexpected token
     sub: Span,
 }
 
-#[derive(Diagnostic)]
+#[derive(Diagnostic)] //~ ERROR cannot find value `__code_34` in this scope
 #[diag(no_crate_example)]
 struct SuggestionsInvalidLiteral {
     #[suggestion(code = 3)]
-    //~^ ERROR `code = "..."`/`code(...)` must contain only string literals
+    //~^ ERROR expected string literal
     sub: Span,
 }
 
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index 513b675e5dd..cd14c7496b3 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -20,11 +20,11 @@ LL |     Bar,
    |
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
-error: `#[diag = ...]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:52:1
+error: expected parentheses: #[diag(...)]
+  --> $DIR/diagnostic-derive.rs:52:8
    |
 LL | #[diag = "E0123"]
-   | ^^^^^^^^^^^^^^^^^
+   |        ^
 
 error: `#[nonsense(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:57:1
@@ -44,35 +44,24 @@ LL | | struct InvalidStructAttr {}
    |
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
-error: `#[diag("...")]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:64:8
-   |
-LL | #[diag("E0123")]
-   |        ^^^^^^^
-   |
-   = help: a diagnostic slug is required as the first argument
-
 error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:64:1
    |
 LL | / #[diag("E0123")]
 LL | |
-LL | |
 LL | | struct InvalidLitNestedAttr {}
    | |______________________________^
    |
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
-error: `#[diag(nonsense(...))]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:75:8
+error: diagnostic slug must be the first argument
+  --> $DIR/diagnostic-derive.rs:74:16
    |
 LL | #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
-   |        ^^^^^^^^^^^^^^^
-   |
-   = help: a diagnostic slug is required as the first argument
+   |                ^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:75:1
+  --> $DIR/diagnostic-derive.rs:74:1
    |
 LL | / #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
 LL | |
@@ -82,120 +71,102 @@ LL | | struct InvalidNestedStructAttr1 {}
    |
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
-error: `#[diag(nonsense = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:81:8
-   |
-LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")]
-   |        ^^^^^^^^^^^^^^^^
-   |
-   = help: only `code` is a valid nested attributes following the slug
-
-error: `#[diag(slug = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:81:42
+error: unknown argument
+  --> $DIR/diagnostic-derive.rs:80:8
    |
 LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")]
-   |                                          ^^^^^^^^^^^^
+   |        ^^^^^^^^
    |
-   = help: only `code` is a valid nested attributes following the slug
+   = note: only the `code` parameter is valid after the slug
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:81:1
+  --> $DIR/diagnostic-derive.rs:80:1
    |
 LL | / #[diag(nonsense = "...", code = "E0123", slug = "foo")]
 LL | |
 LL | |
-LL | |
 LL | | struct InvalidNestedStructAttr2 {}
    | |__________________________________^
    |
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
-error: `#[diag(nonsense = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:88:8
-   |
-LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")]
-   |        ^^^^^^^^^^^^
-
-error: `#[diag(slug = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:88:38
+error: unknown argument
+  --> $DIR/diagnostic-derive.rs:86:8
    |
 LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")]
-   |                                      ^^^^^^^^^^^^
+   |        ^^^^^^^^
    |
-   = help: only `code` is a valid nested attributes following the slug
+   = note: only the `code` parameter is valid after the slug
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:88:1
+  --> $DIR/diagnostic-derive.rs:86:1
    |
 LL | / #[diag(nonsense = 4, code = "E0123", slug = "foo")]
 LL | |
 LL | |
-LL | |
 LL | | struct InvalidNestedStructAttr3 {}
    | |__________________________________^
    |
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
-error: `#[diag(slug = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:95:42
+error: unknown argument
+  --> $DIR/diagnostic-derive.rs:92:42
    |
 LL | #[diag(no_crate_example, code = "E0123", slug = "foo")]
-   |                                          ^^^^^^^^^^^^
+   |                                          ^^^^
    |
-   = help: only `code` is a valid nested attributes following the slug
+   = note: only the `code` parameter is valid after the slug
 
 error: `#[suggestion = ...]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:102:5
+  --> $DIR/diagnostic-derive.rs:99:5
    |
 LL |     #[suggestion = "bar"]
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:109:8
+  --> $DIR/diagnostic-derive.rs:106:8
    |
 LL | #[diag(no_crate_example, code = "E0456")]
    |        ^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:108:8
+  --> $DIR/diagnostic-derive.rs:105:8
    |
 LL | #[diag(no_crate_example, code = "E0123")]
    |        ^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:109:33
+  --> $DIR/diagnostic-derive.rs:106:26
    |
 LL | #[diag(no_crate_example, code = "E0456")]
-   |                                 ^^^^^^^
+   |                          ^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:108:33
+  --> $DIR/diagnostic-derive.rs:105:26
    |
 LL | #[diag(no_crate_example, code = "E0123")]
-   |                                 ^^^^^^^
+   |                          ^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:115:49
+  --> $DIR/diagnostic-derive.rs:112:42
    |
 LL | #[diag(no_crate_example, code = "E0456", code = "E0457")]
-   |                                                 ^^^^^^^
+   |                                          ^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:115:33
+  --> $DIR/diagnostic-derive.rs:112:26
    |
 LL | #[diag(no_crate_example, code = "E0456", code = "E0457")]
-   |                                 ^^^^^^^
+   |                          ^^^^
 
-error: `#[diag(no_crate::example)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:120:26
+error: diagnostic slug must be the first argument
+  --> $DIR/diagnostic-derive.rs:117:43
    |
 LL | #[diag(no_crate_example, no_crate::example, code = "E0456")]
-   |                          ^^^^^^^^^^^^^^^^^
-   |
-   = help: diagnostic slug must be the first argument
+   |                                           ^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:125:1
+  --> $DIR/diagnostic-derive.rs:122:1
    |
 LL | struct KindNotProvided {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -203,7 +174,7 @@ LL | struct KindNotProvided {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:128:1
+  --> $DIR/diagnostic-derive.rs:125:1
    |
 LL | / #[diag(code = "E0456")]
 LL | |
@@ -213,31 +184,31 @@ LL | | struct SlugNotProvided {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/diagnostic-derive.rs:139:5
+  --> $DIR/diagnostic-derive.rs:136:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: `#[nonsense]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:147:5
+  --> $DIR/diagnostic-derive.rs:144:5
    |
 LL |     #[nonsense]
    |     ^^^^^^^^^^^
 
 error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/diagnostic-derive.rs:164:5
+  --> $DIR/diagnostic-derive.rs:161:5
    |
 LL |     #[label(no_crate_label)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `name` doesn't refer to a field on this type
-  --> $DIR/diagnostic-derive.rs:172:46
+  --> $DIR/diagnostic-derive.rs:169:46
    |
 LL |     #[suggestion(no_crate_suggestion, code = "{name}")]
    |                                              ^^^^^^^^
 
 error: invalid format string: expected `'}'` but string was terminated
-  --> $DIR/diagnostic-derive.rs:177:10
+  --> $DIR/diagnostic-derive.rs:174:10
    |
 LL | #[derive(Diagnostic)]
    |          ^^^^^^^^^^ expected `'}'` in format string
@@ -246,7 +217,7 @@ LL | #[derive(Diagnostic)]
    = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: invalid format string: unmatched `}` found
-  --> $DIR/diagnostic-derive.rs:187:10
+  --> $DIR/diagnostic-derive.rs:184:10
    |
 LL | #[derive(Diagnostic)]
    |          ^^^^^^^^^^ unmatched `}` in format string
@@ -255,47 +226,47 @@ LL | #[derive(Diagnostic)]
    = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/diagnostic-derive.rs:207:5
+  --> $DIR/diagnostic-derive.rs:204:5
    |
 LL |     #[label(no_crate_label)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: suggestion without `code = "..."`
-  --> $DIR/diagnostic-derive.rs:226:5
+  --> $DIR/diagnostic-derive.rs:223:5
    |
 LL |     #[suggestion(no_crate_suggestion)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: `#[suggestion(nonsense = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:234:18
+error: invalid nested attribute
+  --> $DIR/diagnostic-derive.rs:231:18
    |
 LL |     #[suggestion(nonsense = "bar")]
-   |                  ^^^^^^^^^^^^^^^^
+   |                  ^^^^^^^^
    |
    = help: only `style`, `code` and `applicability` are valid nested attributes
 
 error: suggestion without `code = "..."`
-  --> $DIR/diagnostic-derive.rs:234:5
+  --> $DIR/diagnostic-derive.rs:231:5
    |
 LL |     #[suggestion(nonsense = "bar")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: `#[suggestion(msg = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:243:18
+error: invalid nested attribute
+  --> $DIR/diagnostic-derive.rs:240:18
    |
 LL |     #[suggestion(msg = "bar")]
-   |                  ^^^^^^^^^^^
+   |                  ^^^
    |
    = help: only `style`, `code` and `applicability` are valid nested attributes
 
 error: suggestion without `code = "..."`
-  --> $DIR/diagnostic-derive.rs:243:5
+  --> $DIR/diagnostic-derive.rs:240:5
    |
 LL |     #[suggestion(msg = "bar")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: wrong field type for suggestion
-  --> $DIR/diagnostic-derive.rs:266:5
+  --> $DIR/diagnostic-derive.rs:263:5
    |
 LL | /     #[suggestion(no_crate_suggestion, code = "This is suggested code")]
 LL | |
@@ -305,81 +276,79 @@ LL | |     suggestion: Applicability,
    = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)`
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:282:24
+  --> $DIR/diagnostic-derive.rs:279:24
    |
 LL |     suggestion: (Span, Span, Applicability),
    |                        ^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:282:18
+  --> $DIR/diagnostic-derive.rs:279:18
    |
 LL |     suggestion: (Span, Span, Applicability),
    |                  ^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:290:33
+  --> $DIR/diagnostic-derive.rs:287:33
    |
 LL |     suggestion: (Applicability, Applicability, Span),
    |                                 ^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:290:18
+  --> $DIR/diagnostic-derive.rs:287:18
    |
 LL |     suggestion: (Applicability, Applicability, Span),
    |                  ^^^^^^^^^^^^^
 
 error: `#[label = ...]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:297:5
+  --> $DIR/diagnostic-derive.rs:294:5
    |
 LL |     #[label = "bar"]
    |     ^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:448:53
+  --> $DIR/diagnostic-derive.rs:445:5
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", applicability = "maybe-incorrect")]
-   |                                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:450:24
+  --> $DIR/diagnostic-derive.rs:447:24
    |
 LL |     suggestion: (Span, Applicability),
    |                        ^^^^^^^^^^^^^
 
 error: invalid applicability
-  --> $DIR/diagnostic-derive.rs:456:53
+  --> $DIR/diagnostic-derive.rs:453:69
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", applicability = "batman")]
-   |                                                     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                                                     ^^^^^^^^
 
 error: the `#[help(...)]` attribute can only be applied to fields of type `Span`, `bool` or `()`
-  --> $DIR/diagnostic-derive.rs:523:5
+  --> $DIR/diagnostic-derive.rs:520:5
    |
 LL |     #[help(no_crate_help)]
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
-error: `#[label(foo)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:532:29
+error: a diagnostic slug must be the first argument to the attribute
+  --> $DIR/diagnostic-derive.rs:529:32
    |
 LL |     #[label(no_crate_label, foo)]
-   |                             ^^^
-   |
-   = help: a diagnostic slug must be the first argument to the attribute
+   |                                ^
 
-error: `#[label(foo = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:540:29
+error: invalid nested attribute
+  --> $DIR/diagnostic-derive.rs:537:29
    |
 LL |     #[label(no_crate_label, foo = "...")]
-   |                             ^^^^^^^^^^^
+   |                             ^^^
 
-error: `#[label(foo(...))]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:548:29
+error: invalid nested attribute
+  --> $DIR/diagnostic-derive.rs:545:29
    |
 LL |     #[label(no_crate_label, foo("..."))]
-   |                             ^^^^^^^^^^
+   |                             ^^^
 
 error: `#[primary_span]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:560:5
+  --> $DIR/diagnostic-derive.rs:557:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
@@ -387,13 +356,13 @@ LL |     #[primary_span]
    = help: the `primary_span` field attribute is not valid for lint diagnostics
 
 error: `#[error(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:580:1
+  --> $DIR/diagnostic-derive.rs:577:1
    |
 LL | #[error(no_crate_example, code = "E0123")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:580:1
+  --> $DIR/diagnostic-derive.rs:577:1
    |
 LL | / #[error(no_crate_example, code = "E0123")]
 LL | |
@@ -405,13 +374,13 @@ LL | | struct ErrorAttribute {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[warn_(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:587:1
+  --> $DIR/diagnostic-derive.rs:584:1
    |
 LL | #[warn_(no_crate_example, code = "E0123")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:587:1
+  --> $DIR/diagnostic-derive.rs:584:1
    |
 LL | / #[warn_(no_crate_example, code = "E0123")]
 LL | |
@@ -423,13 +392,13 @@ LL | | struct WarnAttribute {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[lint(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:594:1
+  --> $DIR/diagnostic-derive.rs:591:1
    |
 LL | #[lint(no_crate_example, code = "E0123")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:594:1
+  --> $DIR/diagnostic-derive.rs:591:1
    |
 LL | / #[lint(no_crate_example, code = "E0123")]
 LL | |
@@ -441,19 +410,19 @@ LL | | struct LintAttributeOnSessionDiag {}
    = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: `#[lint(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:601:1
+  --> $DIR/diagnostic-derive.rs:598:1
    |
 LL | #[lint(no_crate_example, code = "E0123")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[lint(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:601:1
+  --> $DIR/diagnostic-derive.rs:598:1
    |
 LL | #[lint(no_crate_example, code = "E0123")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:601:1
+  --> $DIR/diagnostic-derive.rs:598:1
    |
 LL | / #[lint(no_crate_example, code = "E0123")]
 LL | |
@@ -466,19 +435,19 @@ LL | | struct LintAttributeOnLintDiag {}
    = help: specify the slug as the first argument to the attribute, such as `#[diag(compiletest_example)]`
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:611:53
+  --> $DIR/diagnostic-derive.rs:608:53
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", code = ",,,")]
-   |                                                     ^^^^^^^^^^^^
+   |                                                     ^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:611:39
+  --> $DIR/diagnostic-derive.rs:608:39
    |
 LL |     #[suggestion(no_crate_suggestion, code = "...", code = ",,,")]
-   |                                       ^^^^^^^^^^^^
+   |                                       ^^^^
 
 error: wrong types for suggestion
-  --> $DIR/diagnostic-derive.rs:620:24
+  --> $DIR/diagnostic-derive.rs:617:24
    |
 LL |     suggestion: (Span, usize),
    |                        ^^^^^
@@ -486,7 +455,7 @@ LL |     suggestion: (Span, usize),
    = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
 
 error: wrong types for suggestion
-  --> $DIR/diagnostic-derive.rs:628:17
+  --> $DIR/diagnostic-derive.rs:625:17
    |
 LL |     suggestion: (Span,),
    |                 ^^^^^^^
@@ -494,13 +463,13 @@ LL |     suggestion: (Span,),
    = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)`
 
 error: suggestion without `code = "..."`
-  --> $DIR/diagnostic-derive.rs:635:5
+  --> $DIR/diagnostic-derive.rs:632:5
    |
 LL |     #[suggestion(no_crate_suggestion)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[multipart_suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:642:1
+  --> $DIR/diagnostic-derive.rs:639:1
    |
 LL | #[multipart_suggestion(no_crate_suggestion)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -508,23 +477,21 @@ LL | #[multipart_suggestion(no_crate_suggestion)]
    = help: consider creating a `Subdiagnostic` instead
 
 error: `#[multipart_suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:645:1
-   |
-LL | #[multipart_suggestion()]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider creating a `Subdiagnostic` instead
-
-error: `#[multipart_suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:649:5
+  --> $DIR/diagnostic-derive.rs:646:5
    |
 LL |     #[multipart_suggestion(no_crate_suggestion)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider creating a `Subdiagnostic` instead
 
+error: unexpected end of input, unexpected token in nested attribute, expected ident
+  --> $DIR/diagnostic-derive.rs:642:24
+   |
+LL | #[multipart_suggestion()]
+   |                        ^
+
 error: `#[suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:657:1
+  --> $DIR/diagnostic-derive.rs:654:1
    |
 LL | #[suggestion(no_crate_suggestion, code = "...")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -532,45 +499,39 @@ LL | #[suggestion(no_crate_suggestion, code = "...")]
    = help: `#[label]` and `#[suggestion]` can only be applied to fields
 
 error: `#[label]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:666:1
+  --> $DIR/diagnostic-derive.rs:663:1
    |
 LL | #[label]
    | ^^^^^^^^
    |
    = help: `#[label]` and `#[suggestion]` can only be applied to fields
 
-error: `#[subdiagnostic(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:700:5
+error: `eager` is the only supported nested attribute for `subdiagnostic`
+  --> $DIR/diagnostic-derive.rs:697:7
    |
 LL |     #[subdiagnostic(bad)]
-   |     ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: `eager` is the only supported nested attribute for `subdiagnostic`
+   |       ^^^^^^^^^^^^^^^^^^
 
 error: `#[subdiagnostic = ...]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:708:5
+  --> $DIR/diagnostic-derive.rs:705:5
    |
 LL |     #[subdiagnostic = "bad"]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: `#[subdiagnostic(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:716:5
+error: `eager` is the only supported nested attribute for `subdiagnostic`
+  --> $DIR/diagnostic-derive.rs:713:7
    |
 LL |     #[subdiagnostic(bad, bad)]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: `eager` is the only supported nested attribute for `subdiagnostic`
+   |       ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: `#[subdiagnostic(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:724:5
+error: `eager` is the only supported nested attribute for `subdiagnostic`
+  --> $DIR/diagnostic-derive.rs:721:7
    |
 LL |     #[subdiagnostic("bad")]
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: `eager` is the only supported nested attribute for `subdiagnostic`
+   |       ^^^^^^^^^^^^^^^^^^^^
 
 error: `#[subdiagnostic(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:732:5
+  --> $DIR/diagnostic-derive.rs:729:5
    |
 LL |     #[subdiagnostic(eager)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -578,25 +539,31 @@ LL |     #[subdiagnostic(eager)]
    = help: eager subdiagnostics are not supported on lints
 
 error: expected at least one string literal for `code(...)`
-  --> $DIR/diagnostic-derive.rs:790:18
+  --> $DIR/diagnostic-derive.rs:787:23
    |
 LL |     #[suggestion(code())]
-   |                  ^^^^^^
+   |                       ^
 
 error: `code(...)` must contain only string literals
-  --> $DIR/diagnostic-derive.rs:798:23
+  --> $DIR/diagnostic-derive.rs:795:23
    |
 LL |     #[suggestion(code(foo))]
    |                       ^^^
 
-error: `code = "..."`/`code(...)` must contain only string literals
-  --> $DIR/diagnostic-derive.rs:806:18
+error: unexpected token
+  --> $DIR/diagnostic-derive.rs:795:23
+   |
+LL |     #[suggestion(code(foo))]
+   |                       ^^^
+
+error: expected string literal
+  --> $DIR/diagnostic-derive.rs:804:25
    |
 LL |     #[suggestion(code = 3)]
-   |                  ^^^^^^^^
+   |                         ^
 
 error: `#[suggestion(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:821:5
+  --> $DIR/diagnostic-derive.rs:819:5
    |
 LL |     #[suggestion(no_crate_suggestion, code = "")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -612,61 +579,69 @@ LL | #[nonsense(no_crate_example, code = "E0123")]
    |   ^^^^^^^^
 
 error: cannot find attribute `nonsense` in this scope
-  --> $DIR/diagnostic-derive.rs:147:7
+  --> $DIR/diagnostic-derive.rs:144:7
    |
 LL |     #[nonsense]
    |       ^^^^^^^^
 
 error: cannot find attribute `error` in this scope
-  --> $DIR/diagnostic-derive.rs:580:3
+  --> $DIR/diagnostic-derive.rs:577:3
    |
 LL | #[error(no_crate_example, code = "E0123")]
    |   ^^^^^
 
 error: cannot find attribute `warn_` in this scope
-  --> $DIR/diagnostic-derive.rs:587:3
+  --> $DIR/diagnostic-derive.rs:584:3
    |
 LL | #[warn_(no_crate_example, code = "E0123")]
    |   ^^^^^ help: a built-in attribute with a similar name exists: `warn`
 
 error: cannot find attribute `lint` in this scope
-  --> $DIR/diagnostic-derive.rs:594:3
+  --> $DIR/diagnostic-derive.rs:591:3
    |
 LL | #[lint(no_crate_example, code = "E0123")]
    |   ^^^^ help: a built-in attribute with a similar name exists: `link`
 
 error: cannot find attribute `lint` in this scope
-  --> $DIR/diagnostic-derive.rs:601:3
+  --> $DIR/diagnostic-derive.rs:598:3
    |
 LL | #[lint(no_crate_example, code = "E0123")]
    |   ^^^^ help: a built-in attribute with a similar name exists: `link`
 
 error: cannot find attribute `multipart_suggestion` in this scope
-  --> $DIR/diagnostic-derive.rs:642:3
+  --> $DIR/diagnostic-derive.rs:639:3
    |
 LL | #[multipart_suggestion(no_crate_suggestion)]
    |   ^^^^^^^^^^^^^^^^^^^^
 
 error: cannot find attribute `multipart_suggestion` in this scope
-  --> $DIR/diagnostic-derive.rs:645:3
+  --> $DIR/diagnostic-derive.rs:642:3
    |
 LL | #[multipart_suggestion()]
    |   ^^^^^^^^^^^^^^^^^^^^
 
 error: cannot find attribute `multipart_suggestion` in this scope
-  --> $DIR/diagnostic-derive.rs:649:7
+  --> $DIR/diagnostic-derive.rs:646:7
    |
 LL |     #[multipart_suggestion(no_crate_suggestion)]
    |       ^^^^^^^^^^^^^^^^^^^^
 
 error[E0425]: cannot find value `nonsense` in module `crate::fluent_generated`
-  --> $DIR/diagnostic-derive.rs:70:8
+  --> $DIR/diagnostic-derive.rs:69:8
    |
 LL | #[diag(nonsense, code = "E0123")]
    |        ^^^^^^^^ not found in `crate::fluent_generated`
 
+error[E0425]: cannot find value `__code_34` in this scope
+  --> $DIR/diagnostic-derive.rs:801:10
+   |
+LL | #[derive(Diagnostic)]
+   |          ^^^^^^^^^^ not found in this scope
+   |
+   = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
+
 error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied
-  --> $DIR/diagnostic-derive.rs:341:10
+  --> $DIR/diagnostic-derive.rs:338:10
    |
 LL | #[derive(Diagnostic)]
    |          ^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello`
@@ -676,7 +651,7 @@ note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
   --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:LL:CC
    = note: this error originates in the derive macro `Diagnostic` which comes from the expansion of the macro `forward` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 85 previous errors
+error: aborting due to 84 previous errors
 
 Some errors have detailed explanations: E0277, E0425.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
index c882f7792d5..1d928ca93f9 100644
--- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
+++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs
@@ -82,7 +82,7 @@ struct F {
 
 #[derive(Subdiagnostic)]
 #[label(bug = "...")]
-//~^ ERROR `#[label(bug = ...)]` is not a valid attribute
+//~^ ERROR invalid nested attribute
 //~| ERROR diagnostic slug must be first argument
 struct G {
     #[primary_span]
@@ -92,8 +92,7 @@ struct G {
 
 #[derive(Subdiagnostic)]
 #[label("...")]
-//~^ ERROR `#[label("...")]` is not a valid attribute
-//~| ERROR diagnostic slug must be first argument
+//~^ ERROR unexpected literal in nested attribute, expected ident
 struct H {
     #[primary_span]
     span: Span,
@@ -102,7 +101,7 @@ struct H {
 
 #[derive(Subdiagnostic)]
 #[label(slug = 4)]
-//~^ ERROR `#[label(slug = ...)]` is not a valid attribute
+//~^ ERROR invalid nested attribute
 //~| ERROR diagnostic slug must be first argument
 struct J {
     #[primary_span]
@@ -112,7 +111,7 @@ struct J {
 
 #[derive(Subdiagnostic)]
 #[label(slug("..."))]
-//~^ ERROR `#[label(slug(...))]` is not a valid attribute
+//~^ ERROR invalid nested attribute
 //~| ERROR diagnostic slug must be first argument
 struct K {
     #[primary_span]
@@ -132,7 +131,7 @@ struct L {
 
 #[derive(Subdiagnostic)]
 #[label()]
-//~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute
+//~^ ERROR unexpected end of input, unexpected token in nested attribute, expected ident
 struct M {
     #[primary_span]
     span: Span,
@@ -141,7 +140,7 @@ struct M {
 
 #[derive(Subdiagnostic)]
 #[label(no_crate_example, code = "...")]
-//~^ ERROR `#[label(code = ...)]` is not a valid attribute
+//~^ ERROR invalid nested attribute
 struct N {
     #[primary_span]
     span: Span,
@@ -150,7 +149,7 @@ struct N {
 
 #[derive(Subdiagnostic)]
 #[label(no_crate_example, applicability = "machine-applicable")]
-//~^ ERROR `#[label(applicability = ...)]` is not a valid attribute
+//~^ ERROR invalid nested attribute
 struct O {
     #[primary_span]
     span: Span,
@@ -222,7 +221,7 @@ enum T {
 enum U {
     #[label(code = "...")]
     //~^ ERROR diagnostic slug must be first argument of a `#[label(...)]` attribute
-    //~| ERROR `#[label(code = ...)]` is not a valid attribute
+    //~| ERROR invalid nested attribute
     A {
         #[primary_span]
         span: Span,
@@ -323,7 +322,7 @@ struct AD {
 
 #[derive(Subdiagnostic)]
 #[label(no_crate_example, no_crate::example)]
-//~^ ERROR `#[label(no_crate::example)]` is not a valid attribute
+//~^ ERROR a diagnostic slug must be the first argument to the attribute
 struct AE {
     #[primary_span]
     span: Span,
@@ -537,7 +536,7 @@ struct BA {
 #[derive(Subdiagnostic)]
 #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")]
 //~^ ERROR multipart suggestion without any `#[suggestion_part(...)]` fields
-//~| ERROR `#[multipart_suggestion(code = ...)]` is not a valid attribute
+//~| ERROR invalid nested attribute
 struct BBa {
     var: String,
 }
@@ -554,7 +553,7 @@ struct BBb {
 #[multipart_suggestion(no_crate_example, applicability = "machine-applicable")]
 struct BBc {
     #[suggestion_part()]
-    //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
+    //~^ ERROR unexpected end of input, unexpected token in nested attribute, expected ident
     span1: Span,
 }
 
@@ -574,10 +573,11 @@ struct BD {
     //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
     span1: Span,
     #[suggestion_part()]
-    //~^ ERROR `#[suggestion_part(...)]` attribute without `code = "..."`
+    //~^ ERROR unexpected end of input, unexpected token in nested attribute, expected ident
     span2: Span,
     #[suggestion_part(foo = "bar")]
-    //~^ ERROR `#[suggestion_part(foo = ...)]` is not a valid attribute
+    //~^ ERROR `code` is the only valid nested attribute
+    //~| ERROR expected `,`
     span4: Span,
     #[suggestion_part(code = "...")]
     //~^ ERROR the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
@@ -669,6 +669,7 @@ enum BL {
 struct BM {
     #[suggestion_part(code("foo"))]
     //~^ ERROR expected exactly one string literal for `code = ...`
+    //~| ERROR unexpected token
     span: Span,
     r#type: String,
 }
@@ -678,6 +679,7 @@ struct BM {
 struct BN {
     #[suggestion_part(code("foo", "bar"))]
     //~^ ERROR expected exactly one string literal for `code = ...`
+    //~| ERROR unexpected token
     span: Span,
     r#type: String,
 }
@@ -687,6 +689,7 @@ struct BN {
 struct BO {
     #[suggestion_part(code(3))]
     //~^ ERROR expected exactly one string literal for `code = ...`
+    //~| ERROR unexpected token
     span: Span,
     r#type: String,
 }
@@ -701,10 +704,13 @@ struct BP {
 }
 
 #[derive(Subdiagnostic)]
+//~^ ERROR cannot find value `__code_29` in this scope
+//~| NOTE in this expansion
+//~| NOTE not found in this scope
 #[multipart_suggestion(no_crate_example)]
 struct BQ {
     #[suggestion_part(code = 3)]
-    //~^ ERROR `code = "..."`/`code(...)` must contain only string literals
+    //~^ ERROR expected string literal
     span: Span,
     r#type: String,
 }
@@ -779,7 +785,7 @@ struct SuggestionStyleInvalid1 {
 
 #[derive(Subdiagnostic)]
 #[suggestion(no_crate_example, code = "", style = 42)]
-//~^ ERROR `#[suggestion(style = ...)]` is not a valid attribute
+//~^ ERROR expected `= "xxx"`
 struct SuggestionStyleInvalid2 {
     #[primary_span]
     sub: Span,
@@ -787,7 +793,7 @@ struct SuggestionStyleInvalid2 {
 
 #[derive(Subdiagnostic)]
 #[suggestion(no_crate_example, code = "", style)]
-//~^ ERROR `#[suggestion(style)]` is not a valid attribute
+//~^ ERROR a diagnostic slug must be the first argument to the attribute
 struct SuggestionStyleInvalid3 {
     #[primary_span]
     sub: Span,
@@ -795,7 +801,8 @@ struct SuggestionStyleInvalid3 {
 
 #[derive(Subdiagnostic)]
 #[suggestion(no_crate_example, code = "", style("foo"))]
-//~^ ERROR `#[suggestion(style(...))]` is not a valid attribute
+//~^ ERROR expected `= "xxx"`
+//~| ERROr expected `,`
 struct SuggestionStyleInvalid4 {
     #[primary_span]
     sub: Span,
diff --git a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
index 343134af6bc..4211b91f04a 100644
--- a/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr
@@ -26,11 +26,11 @@ error: `#[label = ...]` is not a valid attribute
 LL | #[label = "..."]
    | ^^^^^^^^^^^^^^^^
 
-error: `#[label(bug = ...)]` is not a valid attribute
+error: invalid nested attribute
   --> $DIR/subdiagnostic-derive.rs:84:9
    |
 LL | #[label(bug = "...")]
-   |         ^^^^^^^^^^^
+   |         ^^^
 
 error: diagnostic slug must be first argument of a `#[label(...)]` attribute
   --> $DIR/subdiagnostic-derive.rs:84:1
@@ -38,110 +38,104 @@ error: diagnostic slug must be first argument of a `#[label(...)]` attribute
 LL | #[label(bug = "...")]
    | ^^^^^^^^^^^^^^^^^^^^^
 
-error: `#[label("...")]` is not a valid attribute
+error: unexpected literal in nested attribute, expected ident
   --> $DIR/subdiagnostic-derive.rs:94:9
    |
 LL | #[label("...")]
    |         ^^^^^
 
-error: diagnostic slug must be first argument of a `#[label(...)]` attribute
-  --> $DIR/subdiagnostic-derive.rs:94:1
-   |
-LL | #[label("...")]
-   | ^^^^^^^^^^^^^^^
-
-error: `#[label(slug = ...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:104:9
+error: invalid nested attribute
+  --> $DIR/subdiagnostic-derive.rs:103:9
    |
 LL | #[label(slug = 4)]
-   |         ^^^^^^^^
+   |         ^^^^
 
 error: diagnostic slug must be first argument of a `#[label(...)]` attribute
-  --> $DIR/subdiagnostic-derive.rs:104:1
+  --> $DIR/subdiagnostic-derive.rs:103:1
    |
 LL | #[label(slug = 4)]
    | ^^^^^^^^^^^^^^^^^^
 
-error: `#[label(slug(...))]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:114:9
+error: invalid nested attribute
+  --> $DIR/subdiagnostic-derive.rs:113:9
    |
 LL | #[label(slug("..."))]
-   |         ^^^^^^^^^^^
+   |         ^^^^
 
 error: diagnostic slug must be first argument of a `#[label(...)]` attribute
-  --> $DIR/subdiagnostic-derive.rs:114:1
+  --> $DIR/subdiagnostic-derive.rs:113:1
    |
 LL | #[label(slug("..."))]
    | ^^^^^^^^^^^^^^^^^^^^^
 
-error: diagnostic slug must be first argument of a `#[label(...)]` attribute
-  --> $DIR/subdiagnostic-derive.rs:134:1
+error: unexpected end of input, unexpected token in nested attribute, expected ident
+  --> $DIR/subdiagnostic-derive.rs:133:9
    |
 LL | #[label()]
-   | ^^^^^^^^^^
+   |         ^
 
-error: `#[label(code = ...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:143:27
+error: invalid nested attribute
+  --> $DIR/subdiagnostic-derive.rs:142:27
    |
 LL | #[label(no_crate_example, code = "...")]
-   |                           ^^^^^^^^^^^^
+   |                           ^^^^
 
-error: `#[label(applicability = ...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:152:27
+error: invalid nested attribute
+  --> $DIR/subdiagnostic-derive.rs:151:27
    |
 LL | #[label(no_crate_example, applicability = "machine-applicable")]
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                           ^^^^^^^^^^^^^
 
 error: unsupported type attribute for subdiagnostic enum
-  --> $DIR/subdiagnostic-derive.rs:161:1
+  --> $DIR/subdiagnostic-derive.rs:160:1
    |
 LL | #[foo]
    | ^^^^^^
 
 error: `#[bar]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:175:5
+  --> $DIR/subdiagnostic-derive.rs:174:5
    |
 LL |     #[bar]
    |     ^^^^^^
 
 error: `#[bar = ...]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:187:5
+  --> $DIR/subdiagnostic-derive.rs:186:5
    |
 LL |     #[bar = "..."]
    |     ^^^^^^^^^^^^^^
 
 error: `#[bar = ...]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:199:5
+  --> $DIR/subdiagnostic-derive.rs:198:5
    |
 LL |     #[bar = 4]
    |     ^^^^^^^^^^
 
 error: `#[bar(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:211:5
+  --> $DIR/subdiagnostic-derive.rs:210:5
    |
 LL |     #[bar("...")]
    |     ^^^^^^^^^^^^^
 
-error: `#[label(code = ...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:223:13
+error: invalid nested attribute
+  --> $DIR/subdiagnostic-derive.rs:222:13
    |
 LL |     #[label(code = "...")]
-   |             ^^^^^^^^^^^^
+   |             ^^^^
 
 error: diagnostic slug must be first argument of a `#[label(...)]` attribute
-  --> $DIR/subdiagnostic-derive.rs:223:5
+  --> $DIR/subdiagnostic-derive.rs:222:5
    |
 LL |     #[label(code = "...")]
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/subdiagnostic-derive.rs:252:5
+  --> $DIR/subdiagnostic-derive.rs:251:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: label without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:249:1
+  --> $DIR/subdiagnostic-derive.rs:248:1
    |
 LL | / #[label(no_crate_example)]
 LL | |
@@ -153,13 +147,13 @@ LL | | }
    | |_^
 
 error: `#[applicability]` is only valid on suggestions
-  --> $DIR/subdiagnostic-derive.rs:262:5
+  --> $DIR/subdiagnostic-derive.rs:261:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: `#[bar]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:272:5
+  --> $DIR/subdiagnostic-derive.rs:271:5
    |
 LL |     #[bar]
    |     ^^^^^^
@@ -167,13 +161,13 @@ LL |     #[bar]
    = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
 
 error: `#[bar = ...]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:283:5
+  --> $DIR/subdiagnostic-derive.rs:282:5
    |
 LL |     #[bar = "..."]
    |     ^^^^^^^^^^^^^^
 
 error: `#[bar(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:294:5
+  --> $DIR/subdiagnostic-derive.rs:293:5
    |
 LL |     #[bar("...")]
    |     ^^^^^^^^^^^^^
@@ -181,7 +175,7 @@ LL |     #[bar("...")]
    = help: only `primary_span`, `applicability` and `skip_arg` are valid field attributes
 
 error: unexpected unsupported untagged union
-  --> $DIR/subdiagnostic-derive.rs:310:1
+  --> $DIR/subdiagnostic-derive.rs:309:1
    |
 LL | / union AC {
 LL | |
@@ -190,76 +184,74 @@ LL | |     b: u64,
 LL | | }
    | |_^
 
-error: `#[label(no_crate::example)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:325:27
+error: a diagnostic slug must be the first argument to the attribute
+  --> $DIR/subdiagnostic-derive.rs:324:44
    |
 LL | #[label(no_crate_example, no_crate::example)]
-   |                           ^^^^^^^^^^^^^^^^^
-   |
-   = help: a diagnostic slug must be the first argument to the attribute
+   |                                            ^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:338:5
+  --> $DIR/subdiagnostic-derive.rs:337:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:335:5
+  --> $DIR/subdiagnostic-derive.rs:334:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: subdiagnostic kind not specified
-  --> $DIR/subdiagnostic-derive.rs:344:8
+  --> $DIR/subdiagnostic-derive.rs:343:8
    |
 LL | struct AG {
    |        ^^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:381:46
+  --> $DIR/subdiagnostic-derive.rs:380:46
    |
 LL | #[suggestion(no_crate_example, code = "...", code = "...")]
-   |                                              ^^^^^^^^^^^^
+   |                                              ^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:381:32
+  --> $DIR/subdiagnostic-derive.rs:380:32
    |
 LL | #[suggestion(no_crate_example, code = "...", code = "...")]
-   |                                ^^^^^^^^^^^^
+   |                                ^^^^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:399:5
+  --> $DIR/subdiagnostic-derive.rs:398:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:396:5
+  --> $DIR/subdiagnostic-derive.rs:395:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: the `#[applicability]` attribute can only be applied to fields of type `Applicability`
-  --> $DIR/subdiagnostic-derive.rs:409:5
+  --> $DIR/subdiagnostic-derive.rs:408:5
    |
 LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: suggestion without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:422:1
+  --> $DIR/subdiagnostic-derive.rs:421:1
    |
 LL | #[suggestion(no_crate_example)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: invalid applicability
-  --> $DIR/subdiagnostic-derive.rs:432:46
+  --> $DIR/subdiagnostic-derive.rs:431:62
    |
 LL | #[suggestion(no_crate_example, code = "...", applicability = "foo")]
-   |                                              ^^^^^^^^^^^^^^^^^^^^^
+   |                                                              ^^^^^
 
 error: suggestion without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:450:1
+  --> $DIR/subdiagnostic-derive.rs:449:1
    |
 LL | / #[suggestion(no_crate_example, code = "...")]
 LL | |
@@ -269,25 +261,25 @@ LL | | }
    | |_^
 
 error: unsupported type attribute for subdiagnostic enum
-  --> $DIR/subdiagnostic-derive.rs:464:1
+  --> $DIR/subdiagnostic-derive.rs:463:1
    |
 LL | #[label]
    | ^^^^^^^^
 
 error: `var` doesn't refer to a field on this type
-  --> $DIR/subdiagnostic-derive.rs:484:39
+  --> $DIR/subdiagnostic-derive.rs:483:39
    |
 LL | #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")]
    |                                       ^^^^^^^
 
 error: `var` doesn't refer to a field on this type
-  --> $DIR/subdiagnostic-derive.rs:503:43
+  --> $DIR/subdiagnostic-derive.rs:502:43
    |
 LL |     #[suggestion(no_crate_example, code = "{var}", applicability = "machine-applicable")]
    |                                           ^^^^^^^
 
 error: `#[suggestion_part]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:526:5
+  --> $DIR/subdiagnostic-derive.rs:525:5
    |
 LL |     #[suggestion_part]
    |     ^^^^^^^^^^^^^^^^^^
@@ -295,7 +287,7 @@ LL |     #[suggestion_part]
    = help: `#[suggestion_part(...)]` is only valid in multipart suggestions, use `#[primary_span]` instead
 
 error: `#[suggestion_part(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:529:5
+  --> $DIR/subdiagnostic-derive.rs:528:5
    |
 LL |     #[suggestion_part(code = "...")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -303,7 +295,7 @@ LL |     #[suggestion_part(code = "...")]
    = help: `#[suggestion_part(...)]` is only valid in multipart suggestions
 
 error: suggestion without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:523:1
+  --> $DIR/subdiagnostic-derive.rs:522:1
    |
 LL | / #[suggestion(no_crate_example, code = "...")]
 LL | |
@@ -314,16 +306,16 @@ LL | |     var: String,
 LL | | }
    | |_^
 
-error: `#[multipart_suggestion(code = ...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:538:42
+error: invalid nested attribute
+  --> $DIR/subdiagnostic-derive.rs:537:42
    |
 LL | #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")]
-   |                                          ^^^^^^^^^^^^
+   |                                          ^^^^
    |
    = help: only `style` and `applicability` are valid nested attributes
 
 error: multipart suggestion without any `#[suggestion_part(...)]` fields
-  --> $DIR/subdiagnostic-derive.rs:538:1
+  --> $DIR/subdiagnostic-derive.rs:537:1
    |
 LL | / #[multipart_suggestion(no_crate_example, code = "...", applicability = "machine-applicable")]
 LL | |
@@ -334,19 +326,19 @@ LL | | }
    | |_^
 
 error: `#[suggestion_part(...)]` attribute without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:548:5
+  --> $DIR/subdiagnostic-derive.rs:547:5
    |
 LL |     #[suggestion_part]
    |     ^^^^^^^^^^^^^^^^^^
 
-error: `#[suggestion_part(...)]` attribute without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:556:5
+error: unexpected end of input, unexpected token in nested attribute, expected ident
+  --> $DIR/subdiagnostic-derive.rs:555:23
    |
 LL |     #[suggestion_part()]
-   |     ^^^^^^^^^^^^^^^^^^^^
+   |                       ^
 
 error: `#[primary_span]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:565:5
+  --> $DIR/subdiagnostic-derive.rs:564:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
@@ -354,7 +346,7 @@ LL |     #[primary_span]
    = help: multipart suggestions use one or more `#[suggestion_part]`s rather than one `#[primary_span]`
 
 error: multipart suggestion without any `#[suggestion_part(...)]` fields
-  --> $DIR/subdiagnostic-derive.rs:562:1
+  --> $DIR/subdiagnostic-derive.rs:561:1
    |
 LL | / #[multipart_suggestion(no_crate_example)]
 LL | |
@@ -366,24 +358,16 @@ LL | | }
    | |_^
 
 error: `#[suggestion_part(...)]` attribute without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:573:5
+  --> $DIR/subdiagnostic-derive.rs:572:5
    |
 LL |     #[suggestion_part]
    |     ^^^^^^^^^^^^^^^^^^
 
-error: `#[suggestion_part(...)]` attribute without `code = "..."`
-  --> $DIR/subdiagnostic-derive.rs:576:5
-   |
-LL |     #[suggestion_part()]
-   |     ^^^^^^^^^^^^^^^^^^^^
-
-error: `#[suggestion_part(foo = ...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:579:23
+error: `code` is the only valid nested attribute
+  --> $DIR/subdiagnostic-derive.rs:578:23
    |
 LL |     #[suggestion_part(foo = "bar")]
-   |                       ^^^^^^^^^^^
-   |
-   = help: `code` is the only valid nested attribute
+   |                       ^^^
 
 error: the `#[suggestion_part(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
   --> $DIR/subdiagnostic-derive.rs:582:5
@@ -397,17 +381,29 @@ error: the `#[suggestion_part(...)]` attribute can only be applied to fields of
 LL |     #[suggestion_part()]
    |     ^^^^^^^^^^^^^^^^^^^^
 
+error: unexpected end of input, unexpected token in nested attribute, expected ident
+  --> $DIR/subdiagnostic-derive.rs:575:23
+   |
+LL |     #[suggestion_part()]
+   |                       ^
+
+error: expected `,`
+  --> $DIR/subdiagnostic-derive.rs:578:27
+   |
+LL |     #[suggestion_part(foo = "bar")]
+   |                           ^
+
 error: specified multiple times
   --> $DIR/subdiagnostic-derive.rs:593:37
    |
 LL |     #[suggestion_part(code = "...", code = ",,,")]
-   |                                     ^^^^^^^^^^^^
+   |                                     ^^^^
    |
 note: previously specified here
   --> $DIR/subdiagnostic-derive.rs:593:23
    |
 LL |     #[suggestion_part(code = "...", code = ",,,")]
-   |                       ^^^^^^^^^^^^
+   |                       ^^^^
 
 error: `#[applicability]` has no effect if all `#[suggestion]`/`#[multipart_suggestion]` attributes have a static `applicability = "..."`
   --> $DIR/subdiagnostic-derive.rs:622:5
@@ -416,49 +412,67 @@ LL |     #[applicability]
    |     ^^^^^^^^^^^^^^^^
 
 error: expected exactly one string literal for `code = ...`
-  --> $DIR/subdiagnostic-derive.rs:670:23
+  --> $DIR/subdiagnostic-derive.rs:670:34
    |
 LL |     #[suggestion_part(code("foo"))]
-   |                       ^^^^^^^^^^^
+   |                                  ^
+
+error: unexpected token
+  --> $DIR/subdiagnostic-derive.rs:670:28
+   |
+LL |     #[suggestion_part(code("foo"))]
+   |                            ^^^^^
 
 error: expected exactly one string literal for `code = ...`
-  --> $DIR/subdiagnostic-derive.rs:679:23
+  --> $DIR/subdiagnostic-derive.rs:680:41
+   |
+LL |     #[suggestion_part(code("foo", "bar"))]
+   |                                         ^
+
+error: unexpected token
+  --> $DIR/subdiagnostic-derive.rs:680:28
    |
 LL |     #[suggestion_part(code("foo", "bar"))]
-   |                       ^^^^^^^^^^^^^^^^^^
+   |                            ^^^^^
 
 error: expected exactly one string literal for `code = ...`
-  --> $DIR/subdiagnostic-derive.rs:688:23
+  --> $DIR/subdiagnostic-derive.rs:690:30
    |
 LL |     #[suggestion_part(code(3))]
-   |                       ^^^^^^^
+   |                              ^
+
+error: unexpected token
+  --> $DIR/subdiagnostic-derive.rs:690:28
+   |
+LL |     #[suggestion_part(code(3))]
+   |                            ^
 
 error: expected exactly one string literal for `code = ...`
-  --> $DIR/subdiagnostic-derive.rs:697:23
+  --> $DIR/subdiagnostic-derive.rs:700:29
    |
 LL |     #[suggestion_part(code())]
-   |                       ^^^^^^
+   |                             ^
 
-error: `code = "..."`/`code(...)` must contain only string literals
-  --> $DIR/subdiagnostic-derive.rs:706:23
+error: expected string literal
+  --> $DIR/subdiagnostic-derive.rs:712:30
    |
 LL |     #[suggestion_part(code = 3)]
-   |                       ^^^^^^^^
+   |                              ^
 
 error: specified multiple times
-  --> $DIR/subdiagnostic-derive.rs:748:61
+  --> $DIR/subdiagnostic-derive.rs:754:1
    |
 LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")]
-   |                                                             ^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
-  --> $DIR/subdiagnostic-derive.rs:748:43
+  --> $DIR/subdiagnostic-derive.rs:754:1
    |
 LL | #[suggestion(no_crate_example, code = "", style = "hidden", style = "normal")]
-   |                                           ^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[suggestion_hidden(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:757:1
+  --> $DIR/subdiagnostic-derive.rs:763:1
    |
 LL | #[suggestion_hidden(no_crate_example, code = "")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -466,7 +480,7 @@ LL | #[suggestion_hidden(no_crate_example, code = "")]
    = help: Use `#[suggestion(..., style = "hidden")]` instead
 
 error: `#[suggestion_hidden(...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:765:1
+  --> $DIR/subdiagnostic-derive.rs:771:1
    |
 LL | #[suggestion_hidden(no_crate_example, code = "", style = "normal")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -474,35 +488,39 @@ LL | #[suggestion_hidden(no_crate_example, code = "", style = "normal")]
    = help: Use `#[suggestion(..., style = "hidden")]` instead
 
 error: invalid suggestion style
-  --> $DIR/subdiagnostic-derive.rs:773:51
+  --> $DIR/subdiagnostic-derive.rs:779:51
    |
 LL | #[suggestion(no_crate_example, code = "", style = "foo")]
    |                                                   ^^^^^
    |
    = help: valid styles are `normal`, `short`, `hidden`, `verbose` and `tool-only`
 
-error: `#[suggestion(style = ...)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:781:43
+error: expected `= "xxx"`
+  --> $DIR/subdiagnostic-derive.rs:787:49
    |
 LL | #[suggestion(no_crate_example, code = "", style = 42)]
-   |                                           ^^^^^^^^^^
+   |                                                 ^
 
-error: `#[suggestion(style)]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:789:43
+error: a diagnostic slug must be the first argument to the attribute
+  --> $DIR/subdiagnostic-derive.rs:795:48
    |
 LL | #[suggestion(no_crate_example, code = "", style)]
-   |                                           ^^^^^
+   |                                                ^
+
+error: expected `= "xxx"`
+  --> $DIR/subdiagnostic-derive.rs:803:48
    |
-   = help: a diagnostic slug must be the first argument to the attribute
+LL | #[suggestion(no_crate_example, code = "", style("foo"))]
+   |                                                ^
 
-error: `#[suggestion(style(...))]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:797:43
+error: expected `,`
+  --> $DIR/subdiagnostic-derive.rs:803:48
    |
 LL | #[suggestion(no_crate_example, code = "", style("foo"))]
-   |                                           ^^^^^^^^^^^^
+   |                                                ^
 
 error: `#[primary_span]` is not a valid attribute
-  --> $DIR/subdiagnostic-derive.rs:808:5
+  --> $DIR/subdiagnostic-derive.rs:815:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
@@ -511,7 +529,7 @@ LL |     #[primary_span]
    = help: to create a suggestion with multiple spans, use `#[multipart_suggestion]` instead
 
 error: suggestion without `#[primary_span]` field
-  --> $DIR/subdiagnostic-derive.rs:805:1
+  --> $DIR/subdiagnostic-derive.rs:812:1
    |
 LL | / #[suggestion(no_crate_example, code = "")]
 LL | |
@@ -529,59 +547,67 @@ LL | #[foo]
    |   ^^^
 
 error: cannot find attribute `foo` in this scope
-  --> $DIR/subdiagnostic-derive.rs:161:3
+  --> $DIR/subdiagnostic-derive.rs:160:3
    |
 LL | #[foo]
    |   ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:175:7
+  --> $DIR/subdiagnostic-derive.rs:174:7
    |
 LL |     #[bar]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:187:7
+  --> $DIR/subdiagnostic-derive.rs:186:7
    |
 LL |     #[bar = "..."]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:199:7
+  --> $DIR/subdiagnostic-derive.rs:198:7
    |
 LL |     #[bar = 4]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:211:7
+  --> $DIR/subdiagnostic-derive.rs:210:7
    |
 LL |     #[bar("...")]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:272:7
+  --> $DIR/subdiagnostic-derive.rs:271:7
    |
 LL |     #[bar]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:283:7
+  --> $DIR/subdiagnostic-derive.rs:282:7
    |
 LL |     #[bar = "..."]
    |       ^^^
 
 error: cannot find attribute `bar` in this scope
-  --> $DIR/subdiagnostic-derive.rs:294:7
+  --> $DIR/subdiagnostic-derive.rs:293:7
    |
 LL |     #[bar("...")]
    |       ^^^
 
 error[E0425]: cannot find value `slug` in module `crate::fluent_generated`
-  --> $DIR/subdiagnostic-derive.rs:124:9
+  --> $DIR/subdiagnostic-derive.rs:123:9
    |
 LL | #[label(slug)]
    |         ^^^^ not found in `crate::fluent_generated`
 
-error: aborting due to 81 previous errors
+error[E0425]: cannot find value `__code_29` in this scope
+  --> $DIR/subdiagnostic-derive.rs:706:10
+   |
+LL | #[derive(Subdiagnostic)]
+   |          ^^^^^^^^^^^^^ not found in this scope
+   |
+   = note: this error originates in the derive macro `Subdiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 86 previous errors
 
 For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/const-generics/defaults/doesnt_infer.stderr b/tests/ui/const-generics/defaults/doesnt_infer.stderr
index 227b2f40223..a61411d6eb6 100644
--- a/tests/ui/const-generics/defaults/doesnt_infer.stderr
+++ b/tests/ui/const-generics/defaults/doesnt_infer.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `Foo<N>`
 LL |     let foo = Foo::foo();
    |         ^^^
    |
-help: consider giving `foo` an explicit type, where the the value of const parameter `N` is specified
+help: consider giving `foo` an explicit type, where the value of const parameter `N` is specified
    |
 LL |     let foo: Foo<N> = Foo::foo();
    |            ++++++++
diff --git a/tests/ui/const-generics/transmute-fail.rs b/tests/ui/const-generics/transmute-fail.rs
new file mode 100644
index 00000000000..d7bf1b47fb5
--- /dev/null
+++ b/tests/ui/const-generics/transmute-fail.rs
@@ -0,0 +1,35 @@
+#![feature(transmute_generic_consts)]
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+fn foo<const W: usize, const H: usize>(v: [[u32;H+1]; W]) -> [[u32; W+1]; H] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute
+  }
+}
+
+fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
+  //~^ ERROR mismatched types
+  //~| ERROR mismatched types
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute between types
+  }
+}
+
+fn baz<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [u32; W * H * H] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute
+  }
+}
+
+fn overflow(v: [[[u32; 8888888]; 9999999]; 777777777]) -> [[[u32; 9999999]; 777777777]; 8888888] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute
+  }
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr
new file mode 100644
index 00000000000..41b098135e8
--- /dev/null
+++ b/tests/ui/const-generics/transmute-fail.stderr
@@ -0,0 +1,52 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-fail.rs:7:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[[u32; H+1]; W]` (generic size [const expr])
+   = note: target type: `[[u32; W+1]; H]` (generic size [const expr])
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-fail.rs:16:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[[u32; H]; W]` (this type does not have a fixed size)
+   = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])
+
+error[E0308]: mismatched types
+  --> $DIR/transmute-fail.rs:12:53
+   |
+LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
+   |                                                     ^ expected `usize`, found `bool`
+
+error[E0308]: mismatched types
+  --> $DIR/transmute-fail.rs:12:67
+   |
+LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
+   |                                                                   ^ expected `usize`, found `bool`
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-fail.rs:23:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[[u32; H]; W]` (generic size [const expr])
+   = note: target type: `[u32; W * H * H]` (generic size [const expr])
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-fail.rs:30:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[[u32; 8888888]; 9999999]; 777777777]` are too big for the current architecture)
+   = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[[u32; 9999999]; 777777777]; 8888888]` are too big for the current architecture)
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0308, E0512.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/const-generics/transmute.rs b/tests/ui/const-generics/transmute.rs
new file mode 100644
index 00000000000..30560a95b5e
--- /dev/null
+++ b/tests/ui/const-generics/transmute.rs
@@ -0,0 +1,83 @@
+// run-pass
+#![feature(generic_const_exprs)]
+#![feature(transmute_generic_consts)]
+#![allow(incomplete_features)]
+
+fn transpose<const W: usize, const H: usize>(v: [[u32;H]; W]) -> [[u32; W]; H] {
+  unsafe {
+    std::mem::transmute(v)
+  }
+}
+
+fn ident<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [[u32; H]; W] {
+  unsafe {
+    std::mem::transmute(v)
+  }
+}
+
+fn flatten<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [u32; W * H] {
+  unsafe {
+    std::mem::transmute(v)
+  }
+}
+
+fn coagulate<const W: usize, const H: usize>(v: [u32; H*W]) -> [[u32; W];H] {
+  unsafe {
+    std::mem::transmute(v)
+  }
+}
+
+fn flatten_3d<const W: usize, const H: usize, const D: usize>(
+  v: [[[u32; D]; H]; W]
+) -> [u32; D * W * H] {
+  unsafe {
+    std::mem::transmute(v)
+  }
+}
+
+fn flatten_somewhat<const W: usize, const H: usize, const D: usize>(
+  v: [[[u32; D]; H]; W]
+) -> [[u32; D * W]; H] {
+  unsafe {
+    std::mem::transmute(v)
+  }
+}
+
+fn known_size<const L: usize>(v: [u16; L]) -> [u8; L * 2] {
+  unsafe {
+    std::mem::transmute(v)
+  }
+}
+
+fn condense_bytes<const L: usize>(v: [u8; L * 2]) -> [u16; L] {
+  unsafe {
+    std::mem::transmute(v)
+  }
+}
+
+fn singleton_each<const L: usize>(v: [u8; L]) -> [[u8;1]; L] {
+  unsafe {
+    std::mem::transmute(v)
+  }
+}
+
+fn transpose_with_const<const W: usize, const H: usize>(
+  v: [[u32; 2 * H]; W + W]
+) -> [[u32; W + W]; 2 * H] {
+  unsafe {
+    std::mem::transmute(v)
+  }
+}
+
+fn main() {
+  let _ = transpose([[0; 8]; 16]);
+  let _ = transpose_with_const::<8,4>([[0; 8]; 16]);
+  let _ = ident([[0; 8]; 16]);
+  let _ = flatten([[0; 13]; 5]);
+  let _: [[_; 5]; 13] = coagulate([0; 65]);
+  let _ = flatten_3d([[[0; 3]; 13]; 5]);
+  let _ = flatten_somewhat([[[0; 3]; 13]; 5]);
+  let _ = known_size([16; 13]);
+  let _: [u16; 5] = condense_bytes([16u8; 10]);
+  let _ = singleton_each([16; 10]);
+}
diff --git a/tests/ui/const-generics/transmute_no_gate.rs b/tests/ui/const-generics/transmute_no_gate.rs
new file mode 100644
index 00000000000..e1ac44390a5
--- /dev/null
+++ b/tests/ui/const-generics/transmute_no_gate.rs
@@ -0,0 +1,91 @@
+// gate-test-transmute_generic_consts
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+fn transpose<const W: usize, const H: usize>(v: [[u32;H]; W]) -> [[u32; W]; H] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute
+  }
+}
+
+fn ident<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [[u32; H]; W] {
+  unsafe {
+    std::mem::transmute(v)
+  }
+}
+
+fn flatten<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [u32; W * H] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute
+  }
+}
+
+fn coagulate<const W: usize, const H: usize>(v: [u32; H*W]) -> [[u32; W];H] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute
+  }
+}
+
+fn flatten_3d<const W: usize, const H: usize, const D: usize>(
+  v: [[[u32; D]; H]; W]
+) -> [u32; D * W * H] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute
+  }
+}
+
+fn flatten_somewhat<const W: usize, const H: usize, const D: usize>(
+  v: [[[u32; D]; H]; W]
+) -> [[u32; D * W]; H] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute
+  }
+}
+
+fn known_size<const L: usize>(v: [u16; L]) -> [u8; L * 2] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute
+  }
+}
+
+fn condense_bytes<const L: usize>(v: [u8; L * 2]) -> [u16; L] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute
+  }
+}
+
+fn singleton_each<const L: usize>(v: [u8; L]) -> [[u8;1]; L] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute
+  }
+}
+
+fn transpose_with_const<const W: usize, const H: usize>(
+  v: [[u32; 2 * H]; W + W]
+) -> [[u32; W + W]; 2 * H] {
+  unsafe {
+    std::mem::transmute(v)
+    //~^ ERROR cannot transmute
+  }
+}
+
+fn main() {
+  let _ = transpose([[0; 8]; 16]);
+  let _ = transpose_with_const::<8,4>([[0; 8]; 16]);
+  let _ = ident([[0; 8]; 16]);
+  let _ = flatten([[0; 13]; 5]);
+  let _: [[_; 5]; 13] = coagulate([0; 65]);
+  let _ = flatten_3d([[[0; 3]; 13]; 5]);
+  let _ = flatten_somewhat([[[0; 3]; 13]; 5]);
+  let _ = known_size([16; 13]);
+  let _: [u16; 5] = condense_bytes([16u8; 10]);
+  let _ = singleton_each([16; 10]);
+}
diff --git a/tests/ui/const-generics/transmute_no_gate.stderr b/tests/ui/const-generics/transmute_no_gate.stderr
new file mode 100644
index 00000000000..9c271b34849
--- /dev/null
+++ b/tests/ui/const-generics/transmute_no_gate.stderr
@@ -0,0 +1,84 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute_no_gate.rs:7:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[[u32; H]; W]` (this type does not have a fixed size)
+   = note: target type: `[[u32; W]; H]` (this type does not have a fixed size)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute_no_gate.rs:20:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[[u32; H]; W]` (this type does not have a fixed size)
+   = note: target type: `[u32; W * H]` (this type does not have a fixed size)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute_no_gate.rs:27:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[u32; H*W]` (this type does not have a fixed size)
+   = note: target type: `[[u32; W]; H]` (this type does not have a fixed size)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute_no_gate.rs:36:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[[[u32; D]; H]; W]` (this type does not have a fixed size)
+   = note: target type: `[u32; D * W * H]` (this type does not have a fixed size)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute_no_gate.rs:45:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[[[u32; D]; H]; W]` (this type does not have a fixed size)
+   = note: target type: `[[u32; D * W]; H]` (this type does not have a fixed size)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute_no_gate.rs:52:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[u16; L]` (this type does not have a fixed size)
+   = note: target type: `[u8; L * 2]` (this type does not have a fixed size)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute_no_gate.rs:59:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[u8; L * 2]` (this type does not have a fixed size)
+   = note: target type: `[u16; L]` (this type does not have a fixed size)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute_no_gate.rs:66:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[u8; L]` (this type does not have a fixed size)
+   = note: target type: `[[u8; 1]; L]` (this type does not have a fixed size)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute_no_gate.rs:75:5
+   |
+LL |     std::mem::transmute(v)
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[[u32; 2 * H]; W + W]` (this type does not have a fixed size)
+   = note: target type: `[[u32; W + W]; 2 * H]` (this type does not have a fixed size)
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0512`.
diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr
index d56e1273f24..835f7f76560 100644
--- a/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr
+++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds-2.stderr
@@ -6,7 +6,7 @@ LL | fn a() -> impl Fn(&u8) -> impl Debug {
 LL |     |x| x
    |     --- ^
    |     |
-   |     hidden type `&u8` captures the anonymous lifetime #1 defined here
+   |     hidden type `&u8` captures the anonymous lifetime as defined here
 
 error: aborting due to previous error
 
diff --git a/tests/ui/inference/issue-83606.stderr b/tests/ui/inference/issue-83606.stderr
index f2ee8692e38..97ed53fb3ce 100644
--- a/tests/ui/inference/issue-83606.stderr
+++ b/tests/ui/inference/issue-83606.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `[usize; N]`
 LL |     let _ = foo("foo");
    |         ^
    |
-help: consider giving this pattern a type, where the the value of const parameter `N` is specified
+help: consider giving this pattern a type, where the value of const parameter `N` is specified
    |
 LL |     let _: [usize; N] = foo("foo");
    |          ++++++++++++
diff --git a/tests/ui/inference/need_type_info/concrete-impl.rs b/tests/ui/inference/need_type_info/concrete-impl.rs
index 72e0e74f323..fc79e6201bd 100644
--- a/tests/ui/inference/need_type_info/concrete-impl.rs
+++ b/tests/ui/inference/need_type_info/concrete-impl.rs
@@ -7,10 +7,13 @@ struct Two;
 struct Struct;
 
 impl Ambiguous<One> for Struct {}
+//~^ NOTE multiple `impl`s satisfying `Struct: Ambiguous<_>` found
 impl Ambiguous<Two> for Struct {}
 
 fn main() {
     <Struct as Ambiguous<_>>::method();
     //~^ ERROR type annotations needed
+    //~| NOTE cannot infer type of the type parameter `A`
     //~| ERROR type annotations needed
+    //~| NOTE infer type of the type parameter `A`
 }
diff --git a/tests/ui/inference/need_type_info/concrete-impl.stderr b/tests/ui/inference/need_type_info/concrete-impl.stderr
index aa32969950d..74c3f6cd5cf 100644
--- a/tests/ui/inference/need_type_info/concrete-impl.stderr
+++ b/tests/ui/inference/need_type_info/concrete-impl.stderr
@@ -1,20 +1,21 @@
 error[E0282]: type annotations needed
-  --> $DIR/concrete-impl.rs:13:5
+  --> $DIR/concrete-impl.rs:14:5
    |
 LL |     <Struct as Ambiguous<_>>::method();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `Ambiguous`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `A` declared on the trait `Ambiguous`
 
 error[E0283]: type annotations needed
-  --> $DIR/concrete-impl.rs:13:5
+  --> $DIR/concrete-impl.rs:14:5
    |
 LL |     <Struct as Ambiguous<_>>::method();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `Ambiguous`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `A` declared on the trait `Ambiguous`
    |
 note: multiple `impl`s satisfying `Struct: Ambiguous<_>` found
   --> $DIR/concrete-impl.rs:9:1
    |
 LL | impl Ambiguous<One> for Struct {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |
 LL | impl Ambiguous<Two> for Struct {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/tests/ui/inference/need_type_info/issue-109905.rs b/tests/ui/inference/need_type_info/issue-109905.rs
new file mode 100644
index 00000000000..99d10a5eae0
--- /dev/null
+++ b/tests/ui/inference/need_type_info/issue-109905.rs
@@ -0,0 +1,25 @@
+// Test that we show the correct type parameter that couldn't be inferred and that we don't
+// end up stating nonsense like "type parameter `'a`" which we used to do.
+
+trait Trait<'a, T> {
+    fn m(self);
+}
+
+impl<'a, A> Trait<'a, A> for () {
+    fn m(self) {}
+}
+
+fn qualified() {
+    <() as Trait<'static, _>>::m(());
+    //~^ ERROR type annotations needed
+    //~| NOTE cannot infer type of the type parameter `T`
+
+}
+
+fn unqualified() {
+    Trait::<'static, _>::m(());
+    //~^ ERROR type annotations needed
+    //~| NOTE cannot infer type of the type parameter `T`
+}
+
+fn main() {}
diff --git a/tests/ui/inference/need_type_info/issue-109905.stderr b/tests/ui/inference/need_type_info/issue-109905.stderr
new file mode 100644
index 00000000000..fcdd50f1422
--- /dev/null
+++ b/tests/ui/inference/need_type_info/issue-109905.stderr
@@ -0,0 +1,15 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-109905.rs:13:5
+   |
+LL |     <() as Trait<'static, _>>::m(());
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the trait `Trait`
+
+error[E0282]: type annotations needed
+  --> $DIR/issue-109905.rs:20:5
+   |
+LL |     Trait::<'static, _>::m(());
+   |     ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `T` declared on the trait `Trait`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/issues/issue-98299.stderr b/tests/ui/issues/issue-98299.stderr
index fd905392a21..4fd9f3030fc 100644
--- a/tests/ui/issues/issue-98299.stderr
+++ b/tests/ui/issues/issue-98299.stderr
@@ -4,7 +4,7 @@ error[E0282]: type annotations needed for `SmallCString<N>`
 LL |     SmallCString::try_from(p).map(|cstr| cstr);
    |                                    ^^^^
    |
-help: consider giving this closure parameter an explicit type, where the the value of const parameter `N` is specified
+help: consider giving this closure parameter an explicit type, where the value of const parameter `N` is specified
    |
 LL |     SmallCString::try_from(p).map(|cstr: SmallCString<N>| cstr);
    |                                        +++++++++++++++++
diff --git a/tests/ui/nll/closure-requirements/escape-argument-callee.stderr b/tests/ui/nll/closure-requirements/escape-argument-callee.stderr
index 363ddfaffe0..c0d95ddaa07 100644
--- a/tests/ui/nll/closure-requirements/escape-argument-callee.stderr
+++ b/tests/ui/nll/closure-requirements/escape-argument-callee.stderr
@@ -6,7 +6,7 @@ LL |         let mut closure = expect_sig(|p, y| *p = y);
    |
    = note: defining type: test::{closure#0} with closure substs [
                i16,
-               for<Region(BrAnon(0, None)), Region(BrAnon(1, None)), Region(BrAnon(2, None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) i32)),
+               for<Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) i32)),
                (),
            ]
 
diff --git a/tests/ui/nll/closure-requirements/escape-argument.stderr b/tests/ui/nll/closure-requirements/escape-argument.stderr
index 5a8462d4dc5..61e2a1ea6f0 100644
--- a/tests/ui/nll/closure-requirements/escape-argument.stderr
+++ b/tests/ui/nll/closure-requirements/escape-argument.stderr
@@ -6,7 +6,7 @@ LL |         let mut closure = expect_sig(|p, y| *p = y);
    |
    = note: defining type: test::{closure#0} with closure substs [
                i16,
-               for<Region(BrAnon(0, None)), Region(BrAnon(1, None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) i32)),
+               for<Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) mut &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) i32)),
                (),
            ]
 
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
index 7da6ce58bf7..5a7b12732df 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr
@@ -6,7 +6,7 @@ LL |         |_outlives1, _outlives2, _outlives3, x, y| {
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for<Region(BrAnon(0, None)), Region(BrAnon(1, None))> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>)),
+               for<Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'_#3r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#4r
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr
index 993687605c4..db2ecc779ef 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr
@@ -6,7 +6,7 @@ LL |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for<Region(BrAnon(0, None)), Region(BrAnon(1, None)), Region(BrAnon(2, None)), Region(BrAnon(3, None)), Region(BrAnon(4, None)), Region(BrAnon(5, None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(4, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(5, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) u32>)),
+               for<Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#3r
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
index 721cd45ded9..1d9dafbe55f 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr
@@ -6,7 +6,7 @@ LL |     foo(cell, |cell_a, cell_x| {
    |
    = note: defining type: case1::{closure#0} with closure substs [
                i32,
-               for<Region(BrAnon(0, None))> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>)),
+               for<Region(BrAnon(None))> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>)),
                (),
            ]
 
@@ -36,7 +36,7 @@ LL |     foo(cell, |cell_a, cell_x| {
    |
    = note: defining type: case2::{closure#0} with closure substs [
                i32,
-               for<Region(BrAnon(0, None))> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>)),
+               for<Region(BrAnon(None))> extern "rust-call" fn((std::cell::Cell<&'_#1r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>)),
                (),
            ]
    = note: number of external vids: 2
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
index 43dfc3bb9f8..85f7fe35c0a 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr
@@ -6,7 +6,7 @@ LL |     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for<Region(BrAnon(0, None)), Region(BrAnon(1, None)), Region(BrAnon(2, None)), Region(BrAnon(3, None)), Region(BrAnon(4, None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(4, None) }) u32>)),
+               for<Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#2r
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
index 96c734226ef..7194843e203 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr
@@ -6,7 +6,7 @@ LL |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for<Region(BrAnon(0, None)), Region(BrAnon(1, None)), Region(BrAnon(2, None)), Region(BrAnon(3, None)), Region(BrAnon(4, None)), Region(BrAnon(5, None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(4, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(5, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) u32>)),
+               for<Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&'_#2r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#3r
diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr
index 03dbd686e49..71f8a1c67c6 100644
--- a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr
@@ -6,7 +6,7 @@ LL |     establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
    |
    = note: defining type: test::{closure#0} with closure substs [
                i16,
-               for<Region(BrAnon(0, None)), Region(BrAnon(1, None))> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>)),
+               for<Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#3r
diff --git a/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
index d716d3de2a1..e1cb97b1c7d 100644
--- a/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr
@@ -6,7 +6,7 @@ LL |         |_outlives1, _outlives2, x, y| {
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for<Region(BrAnon(0, None)), Region(BrAnon(1, None))> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>)),
+               for<Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'_#2r u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) u32>, std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#3r
diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
index b924873fca6..b66e8391c01 100644
--- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr
@@ -6,7 +6,7 @@ LL |     establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for<Region(BrAnon(0, None)), Region(BrAnon(1, None)), Region(BrAnon(2, None)), Region(BrAnon(3, None)), Region(BrAnon(4, None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(4, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>)),
+               for<Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#2r
diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
index 9b25efd0b66..49641fd06fd 100644
--- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
+++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr
@@ -6,7 +6,7 @@ LL |     establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y
    |
    = note: defining type: supply::{closure#0} with closure substs [
                i16,
-               for<Region(BrAnon(0, None)), Region(BrAnon(1, None)), Region(BrAnon(2, None)), Region(BrAnon(3, None)), Region(BrAnon(4, None)), Region(BrAnon(5, None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(2, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(4, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(5, None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(3, None) }) u32>)),
+               for<Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) &'_#1r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 2, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) &'_#2r u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 4, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) u32>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 5, kind: BrAnon(None) }) std::cell::Cell<&ReLateBound(DebruijnIndex(0), BoundRegion { var: 3, kind: BrAnon(None) }) u32>)),
                (),
            ]
    = note: late-bound region is '_#3r
diff --git a/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr
index 6db72b88632..4e34ba51659 100644
--- a/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr
+++ b/tests/ui/nll/closure-requirements/return-wrong-bound-region.stderr
@@ -6,7 +6,7 @@ LL |     expect_sig(|a, b| b); // ought to return `a`
    |
    = note: defining type: test::{closure#0} with closure substs [
                i16,
-               for<Region(BrAnon(0, None)), Region(BrAnon(1, None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) i32,
+               for<Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((&ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) i32, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) i32)) -> &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) i32,
                (),
            ]
 
diff --git a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
index a442cf12d82..2c4a0597554 100644
--- a/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
+++ b/tests/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr
@@ -6,7 +6,7 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
    |
    = note: defining type: generic::<T>::{closure#0} with closure substs [
                i16,
-               for<Region(BrAnon(0, None)), Region(BrAnon(1, None))> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) T)),
+               for<Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) T)),
                (),
            ]
    = note: number of external vids: 2
@@ -28,7 +28,7 @@ LL |     twice(cell, value, |a, b| invoke(a, b));
    |
    = note: defining type: generic_fail::<T>::{closure#0} with closure substs [
                i16,
-               for<Region(BrAnon(0, None)), Region(BrAnon(1, None))> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(0, None) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(1, None) }) T)),
+               for<Region(BrAnon(None)), Region(BrAnon(None))> extern "rust-call" fn((std::option::Option<std::cell::Cell<&'_#1r &ReLateBound(DebruijnIndex(0), BoundRegion { var: 0, kind: BrAnon(None) }) ()>>, &ReLateBound(DebruijnIndex(0), BoundRegion { var: 1, kind: BrAnon(None) }) T)),
                (),
            ]
    = note: late-bound region is '_#2r
diff --git a/tests/ui/parser/dyn-trait-compatibility.rs b/tests/ui/parser/dyn-trait-compatibility.rs
index d2b02cc2af5..6341e053277 100644
--- a/tests/ui/parser/dyn-trait-compatibility.rs
+++ b/tests/ui/parser/dyn-trait-compatibility.rs
@@ -9,6 +9,6 @@ type A2 = dyn<dyn, dyn>;
 type A3 = dyn<<dyn as dyn>::dyn>;
 //~^ ERROR cannot find type `dyn` in this scope
 //~| ERROR cannot find type `dyn` in this scope
-//~| ERROR use of undeclared crate or module `dyn`
+//~| ERROR cannot find trait `dyn` in this scope
 
 fn main() {}
diff --git a/tests/ui/parser/dyn-trait-compatibility.stderr b/tests/ui/parser/dyn-trait-compatibility.stderr
index 0cae01bd1e3..653be5b3b71 100644
--- a/tests/ui/parser/dyn-trait-compatibility.stderr
+++ b/tests/ui/parser/dyn-trait-compatibility.stderr
@@ -4,12 +4,6 @@ error[E0433]: failed to resolve: use of undeclared crate or module `dyn`
 LL | type A1 = dyn::dyn;
    |           ^^^ use of undeclared crate or module `dyn`
 
-error[E0433]: failed to resolve: use of undeclared crate or module `dyn`
-  --> $DIR/dyn-trait-compatibility.rs:9:23
-   |
-LL | type A3 = dyn<<dyn as dyn>::dyn>;
-   |                       ^^^ use of undeclared crate or module `dyn`
-
 error[E0412]: cannot find type `dyn` in this scope
   --> $DIR/dyn-trait-compatibility.rs:1:11
    |
@@ -40,6 +34,12 @@ error[E0412]: cannot find type `dyn` in this scope
 LL | type A3 = dyn<<dyn as dyn>::dyn>;
    |           ^^^ not found in this scope
 
+error[E0405]: cannot find trait `dyn` in this scope
+  --> $DIR/dyn-trait-compatibility.rs:9:23
+   |
+LL | type A3 = dyn<<dyn as dyn>::dyn>;
+   |                       ^^^ not found in this scope
+
 error[E0412]: cannot find type `dyn` in this scope
   --> $DIR/dyn-trait-compatibility.rs:9:16
    |
@@ -48,5 +48,5 @@ LL | type A3 = dyn<<dyn as dyn>::dyn>;
 
 error: aborting due to 8 previous errors
 
-Some errors have detailed explanations: E0412, E0433.
-For more information about an error, try `rustc --explain E0412`.
+Some errors have detailed explanations: E0405, E0412, E0433.
+For more information about an error, try `rustc --explain E0405`.
diff --git a/tests/ui/parser/issues/issue-110014.rs b/tests/ui/parser/issues/issue-110014.rs
new file mode 100644
index 00000000000..69d8f402bb6
--- /dev/null
+++ b/tests/ui/parser/issues/issue-110014.rs
@@ -0,0 +1,3 @@
+fn`2222222222222222222222222222222222222222() {}
+//~^ ERROR unknown start of token: `
+//~^^ ERROR expected identifier, found `2222222222222222222222222222222222222222`
diff --git a/tests/ui/parser/issues/issue-110014.stderr b/tests/ui/parser/issues/issue-110014.stderr
new file mode 100644
index 00000000000..7f1dd592e12
--- /dev/null
+++ b/tests/ui/parser/issues/issue-110014.stderr
@@ -0,0 +1,19 @@
+error: unknown start of token: `
+  --> $DIR/issue-110014.rs:1:3
+   |
+LL | fn`2222222222222222222222222222222222222222() {}
+   |   ^
+   |
+help: Unicode character '`' (Grave Accent) looks like ''' (Single Quote), but it is not
+   |
+LL | fn'2222222222222222222222222222222222222222() {}
+   |   ~
+
+error: expected identifier, found `2222222222222222222222222222222222222222`
+  --> $DIR/issue-110014.rs:1:4
+   |
+LL | fn`2222222222222222222222222222222222222222() {}
+   |    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected identifier
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/rfc-2008-non-exhaustive/struct.stderr b/tests/ui/rfc-2008-non-exhaustive/struct.stderr
index 2cb9ba0d1d1..39b1ef1e078 100644
--- a/tests/ui/rfc-2008-non-exhaustive/struct.stderr
+++ b/tests/ui/rfc-2008-non-exhaustive/struct.stderr
@@ -10,14 +10,11 @@ error[E0603]: tuple struct constructor `TupleStruct` is private
 LL |     let ts_explicit = structs::TupleStruct(640, 480);
    |                                ^^^^^^^^^^^ private tuple struct constructor
    |
-  ::: $DIR/auxiliary/structs.rs:12:24
-   |
-LL | pub struct TupleStruct(pub u16, pub u16);
-   |                        ---------------- a constructor is private if any of the fields is private
-   |
 note: the tuple struct constructor `TupleStruct` is defined here
   --> $DIR/auxiliary/structs.rs:12:1
    |
+LL | #[non_exhaustive]
+   | ----------------- cannot be constructed because it is `#[non_exhaustive]`
 LL | pub struct TupleStruct(pub u16, pub u16);
    | ^^^^^^^^^^^^^^^^^^^^^^
 
@@ -30,6 +27,8 @@ LL |     let us_explicit = structs::UnitStruct;
 note: the unit struct `UnitStruct` is defined here
   --> $DIR/auxiliary/structs.rs:9:1
    |
+LL | #[non_exhaustive]
+   | ----------------- cannot be constructed because it is `#[non_exhaustive]`
 LL | pub struct UnitStruct;
    | ^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/tests/ui/rfc-2008-non-exhaustive/variant.stderr b/tests/ui/rfc-2008-non-exhaustive/variant.stderr
index 720b7b119ce..4083f57a9cd 100644
--- a/tests/ui/rfc-2008-non-exhaustive/variant.stderr
+++ b/tests/ui/rfc-2008-non-exhaustive/variant.stderr
@@ -8,7 +8,9 @@ note: the tuple variant `Tuple` is defined here
   --> $DIR/auxiliary/variants.rs:5:23
    |
 LL |     #[non_exhaustive] Tuple(u32),
-   |                       ^^^^^
+   |     ----------------- ^^^^^
+   |     |
+   |     cannot be constructed because it is `#[non_exhaustive]`
 
 error[E0603]: unit variant `Unit` is private
   --> $DIR/variant.rs:14:47
@@ -20,7 +22,9 @@ note: the unit variant `Unit` is defined here
   --> $DIR/auxiliary/variants.rs:4:23
    |
 LL |     #[non_exhaustive] Unit,
-   |                       ^^^^
+   |     ----------------- ^^^^
+   |     |
+   |     cannot be constructed because it is `#[non_exhaustive]`
 
 error[E0603]: unit variant `Unit` is private
   --> $DIR/variant.rs:18:32
@@ -32,7 +36,9 @@ note: the unit variant `Unit` is defined here
   --> $DIR/auxiliary/variants.rs:4:23
    |
 LL |     #[non_exhaustive] Unit,
-   |                       ^^^^
+   |     ----------------- ^^^^
+   |     |
+   |     cannot be constructed because it is `#[non_exhaustive]`
 
 error[E0603]: tuple variant `Tuple` is private
   --> $DIR/variant.rs:20:32
@@ -44,7 +50,9 @@ note: the tuple variant `Tuple` is defined here
   --> $DIR/auxiliary/variants.rs:5:23
    |
 LL |     #[non_exhaustive] Tuple(u32),
-   |                       ^^^^^
+   |     ----------------- ^^^^^
+   |     |
+   |     cannot be constructed because it is `#[non_exhaustive]`
 
 error[E0603]: tuple variant `Tuple` is private
   --> $DIR/variant.rs:26:35
@@ -56,7 +64,9 @@ note: the tuple variant `Tuple` is defined here
   --> $DIR/auxiliary/variants.rs:5:23
    |
 LL |     #[non_exhaustive] Tuple(u32),
-   |                       ^^^^^
+   |     ----------------- ^^^^^
+   |     |
+   |     cannot be constructed because it is `#[non_exhaustive]`
 
 error[E0639]: cannot create non-exhaustive variant using struct expression
   --> $DIR/variant.rs:8:26
diff --git a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed
index 85d106bc11f..ede0c2e8eaf 100644
--- a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed
+++ b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed
@@ -18,9 +18,11 @@ mod foo {
 fn main() {
     let _: <foo::Baz as crate::foo::Foo>::Bar = ();
     //~^ ERROR absolute paths must start with
-    //~| this is accepted in the current edition
+    //~| WARN this is accepted in the current edition
+    //~| ERROR absolute paths must start with
+    //~| WARN this is accepted in the current edition
 
     let _: <crate::foo::Baz as foo::Foo>::Bar = ();
     //~^ ERROR absolute paths must start with
-    //~| this is accepted in the current edition
+    //~| WARN this is accepted in the current edition
 }
diff --git a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs
index 9ff3c2e5fcf..48b091ddb45 100644
--- a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs
+++ b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs
@@ -18,9 +18,11 @@ mod foo {
 fn main() {
     let _: <foo::Baz as ::foo::Foo>::Bar = ();
     //~^ ERROR absolute paths must start with
-    //~| this is accepted in the current edition
+    //~| WARN this is accepted in the current edition
+    //~| ERROR absolute paths must start with
+    //~| WARN this is accepted in the current edition
 
     let _: <::foo::Baz as foo::Foo>::Bar = ();
     //~^ ERROR absolute paths must start with
-    //~| this is accepted in the current edition
+    //~| WARN this is accepted in the current edition
 }
diff --git a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr
index e1709db0990..497ee440dfd 100644
--- a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr
+++ b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr
@@ -13,7 +13,16 @@ LL | #![deny(absolute_paths_not_starting_with_crate)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-fully-qualified-paths.rs:23:13
+  --> $DIR/edition-lint-fully-qualified-paths.rs:19:25
+   |
+LL |     let _: <foo::Baz as ::foo::Foo>::Bar = ();
+   |                         ^^^^^^^^^^ help: use `crate`: `crate::foo::Foo`
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
+   = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
+
+error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
+  --> $DIR/edition-lint-fully-qualified-paths.rs:25:13
    |
 LL |     let _: <::foo::Baz as foo::Foo>::Bar = ();
    |             ^^^^^^^^^^ help: use `crate`: `crate::foo::Baz`
@@ -21,5 +30,5 @@ LL |     let _: <::foo::Baz as foo::Foo>::Bar = ();
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs
index 471a6b836b5..8e43b7249f7 100644
--- a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs
+++ b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.rs
@@ -18,6 +18,6 @@ fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String { //~ ERROR expec
 
 fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
 //~^ ERROR expected trait, found struct
-//~| ERROR use of undeclared type `Unresolved`
+//~| ERROR cannot find trait `Unresolved` in this scope
 
 fn main() {}
diff --git a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
index 5be33498641..0020f9e416d 100644
--- a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
+++ b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
@@ -1,9 +1,3 @@
-error[E0433]: failed to resolve: use of undeclared type `Unresolved`
-  --> $DIR/assoc_type_bound_with_struct.rs:19:31
-   |
-LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
-   |                               ^^^^^^^^^^ use of undeclared type `Unresolved`
-
 error[E0404]: expected trait, found struct `String`
   --> $DIR/assoc_type_bound_with_struct.rs:5:46
    |
@@ -76,6 +70,12 @@ help: a trait with a similar name exists
 LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: ToString {
    |                                                         ~~~~~~~~
 
+error[E0405]: cannot find trait `Unresolved` in this scope
+  --> $DIR/assoc_type_bound_with_struct.rs:19:31
+   |
+LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
+   |                               ^^^^^^^^^^ not found in this scope
+
 error[E0404]: expected trait, found struct `String`
   --> $DIR/assoc_type_bound_with_struct.rs:19:51
    |
@@ -87,5 +87,5 @@ LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
 
 error: aborting due to 6 previous errors
 
-Some errors have detailed explanations: E0404, E0433.
+Some errors have detailed explanations: E0404, E0405.
 For more information about an error, try `rustc --explain E0404`.
diff --git a/tests/ui/ufcs/ufcs-partially-resolved.rs b/tests/ui/ufcs/ufcs-partially-resolved.rs
index e6470aa6d64..712668728c9 100644
--- a/tests/ui/ufcs/ufcs-partially-resolved.rs
+++ b/tests/ui/ufcs/ufcs-partially-resolved.rs
@@ -17,37 +17,37 @@ type A = u32;
 
 fn main() {
     let _: <u8 as Tr>::N; //~ ERROR cannot find associated type `N` in trait `Tr`
-    let _: <u8 as E>::N; //~ ERROR cannot find associated type `N` in enum `E`
-    let _: <u8 as A>::N; //~ ERROR cannot find associated type `N` in `A`
+    let _: <u8 as E>::N; //~ ERROR expected trait, found enum `E`
+    let _: <u8 as A>::N; //~ ERROR expected trait, found type alias `A`
     <u8 as Tr>::N; //~ ERROR cannot find method or associated constant `N` in trait `Tr`
-    <u8 as E>::N; //~ ERROR cannot find method or associated constant `N` in enum `E`
-    <u8 as A>::N; //~ ERROR cannot find method or associated constant `N` in `A`
+    <u8 as E>::N; //~ ERROR expected trait, found enum `E`
+    <u8 as A>::N; //~ ERROR expected trait, found type alias `A`
     let _: <u8 as Tr>::Y; // OK
-    let _: <u8 as E>::Y; //~ ERROR expected associated type, found variant `E::Y`
+    let _: <u8 as E>::Y; //~ ERROR expected trait, found enum `E`
     <u8 as Tr>::Y; // OK
-    <u8 as E>::Y; //~ ERROR expected method or associated constant, found unit variant `E::Y`
+    <u8 as E>::Y; //~ ERROR expected trait, found enum `E`
 
     let _: <u8 as Tr>::N::NN; //~ ERROR cannot find associated type `N` in trait `Tr`
-    let _: <u8 as E>::N::NN; //~ ERROR cannot find associated type `N` in enum `E`
-    let _: <u8 as A>::N::NN; //~ ERROR cannot find associated type `N` in `A`
+    let _: <u8 as E>::N::NN; //~ ERROR expected trait, found enum `E`
+    let _: <u8 as A>::N::NN; //~ ERROR expected trait, found type alias `A`
     <u8 as Tr>::N::NN; //~ ERROR cannot find associated type `N` in trait `Tr`
-    <u8 as E>::N::NN; //~ ERROR cannot find associated type `N` in enum `E`
-    <u8 as A>::N::NN; //~ ERROR cannot find associated type `N` in `A`
+    <u8 as E>::N::NN; //~ ERROR expected trait, found enum `E`
+    <u8 as A>::N::NN; //~ ERROR expected trait, found type alias `A`
     let _: <u8 as Tr>::Y::NN; //~ ERROR ambiguous associated type
-    let _: <u8 as E>::Y::NN; //~ ERROR expected associated type, found variant `E::Y`
+    let _: <u8 as E>::Y::NN; //~ ERROR expected trait, found enum `E`
     <u8 as Tr>::Y::NN; //~ ERROR no associated item named `NN` found for type `u16`
-    <u8 as E>::Y::NN; //~ ERROR expected associated type, found variant `E::Y`
+    <u8 as E>::Y::NN; //~ ERROR expected trait, found enum `E`
 
-    let _: <u8 as Tr::N>::NN; //~ ERROR cannot find associated type `NN` in `Tr::N`
-    let _: <u8 as E::N>::NN; //~ ERROR cannot find associated type `NN` in `E::N`
-    let _: <u8 as A::N>::NN; //~ ERROR cannot find associated type `NN` in `A::N`
-    <u8 as Tr::N>::NN; //~ ERROR cannot find method or associated constant `NN` in `Tr::N`
-    <u8 as E::N>::NN; //~ ERROR cannot find method or associated constant `NN` in `E::N`
-    <u8 as A::N>::NN; //~ ERROR cannot find method or associated constant `NN` in `A::N`
-    let _: <u8 as Tr::Y>::NN; //~ ERROR cannot find associated type `NN` in `Tr::Y`
-    let _: <u8 as E::Y>::NN; //~ ERROR failed to resolve: `Y` is a variant, not a module
-    <u8 as Tr::Y>::NN; //~ ERROR cannot find method or associated constant `NN` in `Tr::Y`
-    <u8 as E::Y>::NN; //~ ERROR failed to resolve: `Y` is a variant, not a module
+    let _: <u8 as Tr::N>::NN; //~ ERROR cannot find trait `N` in trait `Tr`
+    let _: <u8 as E::N>::NN; //~ ERROR cannot find trait `N` in enum `E`
+    let _: <u8 as A::N>::NN; //~ ERROR cannot find trait `N` in `A`
+    <u8 as Tr::N>::NN; //~ ERROR cannot find trait `N` in trait `Tr`
+    <u8 as E::N>::NN; //~ ERROR cannot find trait `N` in enum `E`
+    <u8 as A::N>::NN; //~ ERROR cannot find trait `N` in `A`
+    let _: <u8 as Tr::Y>::NN; //~ ERROR expected trait, found associated type `Tr::Y
+    let _: <u8 as E::Y>::NN; //~ ERROR expected trait, found variant `E::Y`
+    <u8 as Tr::Y>::NN; //~ ERROR expected trait, found associated type `Tr::Y`
+    <u8 as E::Y>::NN; //~ ERROR expected trait, found variant `E::Y`
 
     let _: <u8 as Dr>::Z; //~ ERROR expected associated type, found associated function `Dr::Z`
     <u8 as Dr>::X; //~ ERROR expected method or associated constant, found associated type `Dr::X`
diff --git a/tests/ui/ufcs/ufcs-partially-resolved.stderr b/tests/ui/ufcs/ufcs-partially-resolved.stderr
index 72fccea8ae3..eef55c8dc68 100644
--- a/tests/ui/ufcs/ufcs-partially-resolved.stderr
+++ b/tests/ui/ufcs/ufcs-partially-resolved.stderr
@@ -1,15 +1,3 @@
-error[E0433]: failed to resolve: `Y` is a variant, not a module
-  --> $DIR/ufcs-partially-resolved.rs:48:22
-   |
-LL |     let _: <u8 as E::Y>::NN;
-   |                      ^ `Y` is a variant, not a module
-
-error[E0433]: failed to resolve: `Y` is a variant, not a module
-  --> $DIR/ufcs-partially-resolved.rs:50:15
-   |
-LL |     <u8 as E::Y>::NN;
-   |               ^ `Y` is a variant, not a module
-
 error[E0576]: cannot find associated type `N` in trait `Tr`
   --> $DIR/ufcs-partially-resolved.rs:19:24
    |
@@ -19,17 +7,25 @@ LL |     type Y = u16;
 LL |     let _: <u8 as Tr>::N;
    |                        ^ help: an associated type with a similar name exists: `Y`
 
-error[E0576]: cannot find associated type `N` in enum `E`
-  --> $DIR/ufcs-partially-resolved.rs:20:23
+error[E0404]: expected trait, found enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:20:19
    |
 LL |     let _: <u8 as E>::N;
-   |                       ^ not found in `E`
+   |                   ^ help: a trait with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: similarly named trait `Eq` defined here
 
-error[E0576]: cannot find associated type `N` in `A`
-  --> $DIR/ufcs-partially-resolved.rs:21:23
+error[E0404]: expected trait, found type alias `A`
+  --> $DIR/ufcs-partially-resolved.rs:21:19
    |
 LL |     let _: <u8 as A>::N;
-   |                       ^ not found in `A`
+   |                   ^ type aliases cannot be used as traits
+   |
+help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
+   |
+LL | trait A = u32;
+   |
 
 error[E0576]: cannot find method or associated constant `N` in trait `Tr`
   --> $DIR/ufcs-partially-resolved.rs:22:17
@@ -40,29 +36,43 @@ LL |     fn Y() {}
 LL |     <u8 as Tr>::N;
    |                 ^ help: an associated function with a similar name exists: `Y`
 
-error[E0576]: cannot find method or associated constant `N` in enum `E`
-  --> $DIR/ufcs-partially-resolved.rs:23:16
+error[E0404]: expected trait, found enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:23:12
    |
 LL |     <u8 as E>::N;
-   |                ^ not found in `E`
+   |            ^ help: a trait with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: similarly named trait `Eq` defined here
 
-error[E0576]: cannot find method or associated constant `N` in `A`
-  --> $DIR/ufcs-partially-resolved.rs:24:16
+error[E0404]: expected trait, found type alias `A`
+  --> $DIR/ufcs-partially-resolved.rs:24:12
    |
 LL |     <u8 as A>::N;
-   |                ^ not found in `A`
+   |            ^ type aliases cannot be used as traits
+   |
+help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
+   |
+LL | trait A = u32;
+   |
 
-error[E0575]: expected associated type, found variant `E::Y`
-  --> $DIR/ufcs-partially-resolved.rs:26:12
+error[E0404]: expected trait, found enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:26:19
    |
 LL |     let _: <u8 as E>::Y;
-   |            ^^^^^^^^^^^^ not a associated type
+   |                   ^ help: a trait with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: similarly named trait `Eq` defined here
 
-error[E0575]: expected method or associated constant, found unit variant `E::Y`
-  --> $DIR/ufcs-partially-resolved.rs:28:5
+error[E0404]: expected trait, found enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:28:12
    |
 LL |     <u8 as E>::Y;
-   |     ^^^^^^^^^^^^ not a method or associated constant
+   |            ^ help: a trait with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: similarly named trait `Eq` defined here
 
 error[E0576]: cannot find associated type `N` in trait `Tr`
   --> $DIR/ufcs-partially-resolved.rs:30:24
@@ -73,17 +83,25 @@ LL |     type Y = u16;
 LL |     let _: <u8 as Tr>::N::NN;
    |                        ^ help: an associated type with a similar name exists: `Y`
 
-error[E0576]: cannot find associated type `N` in enum `E`
-  --> $DIR/ufcs-partially-resolved.rs:31:23
+error[E0404]: expected trait, found enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:31:19
    |
 LL |     let _: <u8 as E>::N::NN;
-   |                       ^ not found in `E`
+   |                   ^ help: a trait with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: similarly named trait `Eq` defined here
 
-error[E0576]: cannot find associated type `N` in `A`
-  --> $DIR/ufcs-partially-resolved.rs:32:23
+error[E0404]: expected trait, found type alias `A`
+  --> $DIR/ufcs-partially-resolved.rs:32:19
    |
 LL |     let _: <u8 as A>::N::NN;
-   |                       ^ not found in `A`
+   |                   ^ type aliases cannot be used as traits
+   |
+help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
+   |
+LL | trait A = u32;
+   |
 
 error[E0576]: cannot find associated type `N` in trait `Tr`
   --> $DIR/ufcs-partially-resolved.rs:33:17
@@ -94,77 +112,103 @@ LL |     type Y = u16;
 LL |     <u8 as Tr>::N::NN;
    |                 ^ help: an associated type with a similar name exists: `Y`
 
-error[E0576]: cannot find associated type `N` in enum `E`
-  --> $DIR/ufcs-partially-resolved.rs:34:16
+error[E0404]: expected trait, found enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:34:12
    |
 LL |     <u8 as E>::N::NN;
-   |                ^ not found in `E`
+   |            ^ help: a trait with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: similarly named trait `Eq` defined here
 
-error[E0576]: cannot find associated type `N` in `A`
-  --> $DIR/ufcs-partially-resolved.rs:35:16
+error[E0404]: expected trait, found type alias `A`
+  --> $DIR/ufcs-partially-resolved.rs:35:12
    |
 LL |     <u8 as A>::N::NN;
-   |                ^ not found in `A`
+   |            ^ type aliases cannot be used as traits
+   |
+help: you might have meant to use `#![feature(trait_alias)]` instead of a `type` alias
+   |
+LL | trait A = u32;
+   |
 
-error[E0575]: expected associated type, found variant `E::Y`
-  --> $DIR/ufcs-partially-resolved.rs:37:12
+error[E0404]: expected trait, found enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:37:19
    |
 LL |     let _: <u8 as E>::Y::NN;
-   |            ^^^^^^^^^^^^^^^^ not a associated type
+   |                   ^ help: a trait with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: similarly named trait `Eq` defined here
 
-error[E0575]: expected associated type, found variant `E::Y`
-  --> $DIR/ufcs-partially-resolved.rs:39:5
+error[E0404]: expected trait, found enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:39:12
    |
 LL |     <u8 as E>::Y::NN;
-   |     ^^^^^^^^^^^^^^^^ not a associated type
+   |            ^ help: a trait with a similar name exists: `Eq`
+  --> $SRC_DIR/core/src/cmp.rs:LL:COL
+   |
+   = note: similarly named trait `Eq` defined here
 
-error[E0576]: cannot find associated type `NN` in `Tr::N`
-  --> $DIR/ufcs-partially-resolved.rs:41:27
+error[E0405]: cannot find trait `N` in trait `Tr`
+  --> $DIR/ufcs-partially-resolved.rs:41:23
    |
 LL |     let _: <u8 as Tr::N>::NN;
-   |                           ^^ not found in `Tr::N`
+   |                       ^ not found in `Tr`
 
-error[E0576]: cannot find associated type `NN` in `E::N`
-  --> $DIR/ufcs-partially-resolved.rs:42:26
+error[E0405]: cannot find trait `N` in enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:42:22
    |
 LL |     let _: <u8 as E::N>::NN;
-   |                          ^^ not found in `E::N`
+   |                      ^ not found in `E`
 
-error[E0576]: cannot find associated type `NN` in `A::N`
-  --> $DIR/ufcs-partially-resolved.rs:43:26
+error[E0405]: cannot find trait `N` in `A`
+  --> $DIR/ufcs-partially-resolved.rs:43:22
    |
 LL |     let _: <u8 as A::N>::NN;
-   |                          ^^ not found in `A::N`
+   |                      ^ not found in `A`
 
-error[E0576]: cannot find method or associated constant `NN` in `Tr::N`
-  --> $DIR/ufcs-partially-resolved.rs:44:20
+error[E0405]: cannot find trait `N` in trait `Tr`
+  --> $DIR/ufcs-partially-resolved.rs:44:16
    |
 LL |     <u8 as Tr::N>::NN;
-   |                    ^^ not found in `Tr::N`
+   |                ^ not found in `Tr`
 
-error[E0576]: cannot find method or associated constant `NN` in `E::N`
-  --> $DIR/ufcs-partially-resolved.rs:45:19
+error[E0405]: cannot find trait `N` in enum `E`
+  --> $DIR/ufcs-partially-resolved.rs:45:15
    |
 LL |     <u8 as E::N>::NN;
-   |                   ^^ not found in `E::N`
+   |               ^ not found in `E`
 
-error[E0576]: cannot find method or associated constant `NN` in `A::N`
-  --> $DIR/ufcs-partially-resolved.rs:46:19
+error[E0405]: cannot find trait `N` in `A`
+  --> $DIR/ufcs-partially-resolved.rs:46:15
    |
 LL |     <u8 as A::N>::NN;
-   |                   ^^ not found in `A::N`
+   |               ^ not found in `A`
 
-error[E0576]: cannot find associated type `NN` in `Tr::Y`
-  --> $DIR/ufcs-partially-resolved.rs:47:27
+error[E0404]: expected trait, found associated type `Tr::Y`
+  --> $DIR/ufcs-partially-resolved.rs:47:19
    |
 LL |     let _: <u8 as Tr::Y>::NN;
-   |                           ^^ not found in `Tr::Y`
+   |                   ^^^^^ not a trait
+
+error[E0404]: expected trait, found variant `E::Y`
+  --> $DIR/ufcs-partially-resolved.rs:48:19
+   |
+LL |     let _: <u8 as E::Y>::NN;
+   |                   ^^^^ not a trait
 
-error[E0576]: cannot find method or associated constant `NN` in `Tr::Y`
-  --> $DIR/ufcs-partially-resolved.rs:49:20
+error[E0404]: expected trait, found associated type `Tr::Y`
+  --> $DIR/ufcs-partially-resolved.rs:49:12
    |
 LL |     <u8 as Tr::Y>::NN;
-   |                    ^^ not found in `Tr::Y`
+   |            ^^^^^ not a trait
+
+error[E0404]: expected trait, found variant `E::Y`
+  --> $DIR/ufcs-partially-resolved.rs:50:12
+   |
+LL |     <u8 as E::Y>::NN;
+   |            ^^^^ not a trait
 
 error[E0575]: expected associated type, found associated function `Dr::Z`
   --> $DIR/ufcs-partially-resolved.rs:52:12
@@ -226,5 +270,5 @@ LL |     <u8 as Dr>::X::N;
 
 error: aborting due to 32 previous errors
 
-Some errors have detailed explanations: E0223, E0433, E0575, E0576, E0599.
+Some errors have detailed explanations: E0223, E0404, E0405, E0575, E0576, E0599.
 For more information about an error, try `rustc --explain E0223`.
diff --git a/triagebot.toml b/triagebot.toml
index 2d7be7d1273..5f4de0562f8 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -470,8 +470,8 @@ cc = ["@rust-lang/style"]
 
 [mentions."Cargo.lock"]
 message = """
-These commits modify the `Cargo.lock` file. Random changes to `Cargo.lock` can be introduced when switching branches and rebasing PRs. 
-This was probably unintentional and should be reverted before this PR is merged. 
+These commits modify the `Cargo.lock` file. Random changes to `Cargo.lock` can be introduced when switching branches and rebasing PRs.
+This was probably unintentional and should be reverted before this PR is merged.
 
 If this was intentional then you can ignore this comment.
 """
@@ -499,7 +499,6 @@ compiler-team = [
 ]
 compiler-team-contributors = [
     "@compiler-errors",
-    "@eholk",
     "@jackh726",
     "@TaKO8Ki",
     "@WaffleLapkin",