about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml11
-rw-r--r--Cargo.lock12
-rw-r--r--RELEASES.md105
-rw-r--r--compiler/rustc_arena/src/lib.rs87
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs3
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs11
-rw-r--r--compiler/rustc_borrowck/src/consumers.rs2
-rw-r--r--compiler/rustc_borrowck/src/dataflow.rs19
-rw-r--r--compiler/rustc_borrowck/src/invalidation.rs6
-rw-r--r--compiler/rustc_borrowck/src/lib.rs10
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs8
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs5
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs38
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/analyze.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/debuginfo.rs54
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs4
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs64
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs16
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs14
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs7
-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.rs4
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/resolver.rs13
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs60
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0132.md2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0152.md4
-rw-r--r--compiler/rustc_errors/src/lib.rs4
-rw-r--r--compiler/rustc_expand/src/mbe/macro_parser.rs6
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs2
-rw-r--r--compiler/rustc_expand/src/mbe/metavar_expr.rs12
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs7
-rw-r--r--compiler/rustc_feature/src/active.rs2
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs1
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl3
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/bounds.rs29
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs9
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs32
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs13
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs29
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs42
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/method/prelude2021.rs21
-rw-r--r--compiler/rustc_incremental/src/persist/fs.rs20
-rw-r--r--compiler/rustc_infer/src/traits/mod.rs24
-rw-r--r--compiler/rustc_lint/src/reference_casting.rs49
-rw-r--r--compiler/rustc_macros/src/serialize.rs4
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs7
-rw-r--r--compiler/rustc_middle/src/mir/coverage.rs15
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs4
-rw-r--r--compiler/rustc_middle/src/mir/patch.rs8
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs9
-rw-r--r--compiler/rustc_middle/src/mir/spanview.rs45
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs30
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs130
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs5
-rw-r--r--compiler/rustc_middle/src/query/mod.rs1
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs9
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs1
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse/instruction.rs19
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs14
-rw-r--r--compiler/rustc_mir_build/src/lints.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/direction.rs173
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/engine.rs41
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/fmt.rs32
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/graphviz.rs6
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/lattice.rs94
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/mod.rs111
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/tests.rs7
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs69
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/initialized.rs778
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/liveness.rs90
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/mod.rs760
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs91
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/builder.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs63
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs4
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs4
-rw-r--r--compiler/rustc_mir_transform/src/const_prop_lint.rs4
-rw-r--r--compiler/rustc_mir_transform/src/coverage/counters.rs87
-rw-r--r--compiler/rustc_mir_transform/src/coverage/debug.rs73
-rw-r--r--compiler/rustc_mir_transform/src/coverage/graph.rs4
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mod.rs68
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs4
-rw-r--r--compiler/rustc_mir_transform/src/coverage/tests.rs9
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs71
-rw-r--r--compiler/rustc_mir_transform/src/deduce_param_attrs.rs7
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs4
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs86
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs35
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs10
-rw-r--r--compiler/rustc_mir_transform/src/ref_prop.rs8
-rw-r--r--compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs20
-rw-r--r--compiler/rustc_mir_transform/src/remove_uninit_drops.rs7
-rw-r--r--compiler/rustc_mir_transform/src/separate_const_switch.rs8
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs17
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs4
-rw-r--r--compiler/rustc_parse/messages.ftl4
-rw-r--r--compiler/rustc_parse/src/errors.rs19
-rw-r--r--compiler/rustc_parse/src/lexer/unescape_error_reporting.rs22
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs43
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs33
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs87
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs24
-rw-r--r--compiler/rustc_passes/src/layout_test.rs1
-rw-r--r--compiler/rustc_passes/src/liveness.rs1
-rw-r--r--compiler/rustc_query_system/src/query/caches.rs56
-rw-r--r--compiler/rustc_resolve/src/rustdoc.rs75
-rw-r--r--compiler/rustc_session/src/config.rs12
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs4
-rw-r--r--compiler/rustc_smir/src/stable_mir/mod.rs16
-rw-r--r--compiler/rustc_smir/src/stable_mir/ty.rs3
-rw-r--r--compiler/rustc_span/src/lib.rs37
-rw-r--r--compiler/rustc_span/src/symbol.rs11
-rw-r--r--compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs1
-rw-r--r--compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs1
-rw-r--r--compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs1
-rw-r--r--compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs1
-rw-r--r--compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs1
-rw-r--r--compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs1
-rw-r--r--compiler/rustc_target/src/spec/mod.rs56
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs13
-rw-r--r--compiler/rustc_type_ir/src/structural_impls.rs1
-rw-r--r--library/alloc/src/boxed.rs4
-rw-r--r--library/alloc/src/lib.rs3
-rw-r--r--library/alloc/src/str.rs2
-rw-r--r--library/alloc/src/sync.rs6
-rw-r--r--library/core/src/cmp.rs16
-rw-r--r--library/core/src/ffi/c_str.rs12
-rw-r--r--library/core/src/intrinsics.rs2
-rw-r--r--library/core/src/intrinsics/mir.rs9
-rw-r--r--library/core/src/lib.rs4
-rw-r--r--library/core/src/num/int_macros.rs1
-rw-r--r--library/core/src/num/uint_macros.rs1
-rw-r--r--library/core/src/ptr/const_ptr.rs1
-rw-r--r--library/core/src/ptr/mut_ptr.rs1
-rw-r--r--library/proc_macro/src/lib.rs38
-rw-r--r--library/std/src/collections/hash/map.rs6
-rw-r--r--library/std/src/collections/hash/set.rs7
-rw-r--r--library/std/src/error.rs2
-rw-r--r--library/std/src/f32.rs10
-rw-r--r--library/std/src/f64.rs10
-rw-r--r--library/std/src/io/mod.rs6
-rw-r--r--library/std/src/lib.rs3
-rw-r--r--library/std/src/sync/mpsc/mod.rs5
-rw-r--r--library/std/src/sys/solid/os.rs30
-rw-r--r--library/std/src/sys/unix/os.rs21
-rw-r--r--library/std/src/sys/wasi/os.rs23
-rw-r--r--library/std/src/sys/windows/os.rs8
-rw-r--r--library/std/src/sys_common/thread_parking/id.rs17
-rw-r--r--library/std/tests/env.rs20
-rw-r--r--src/ci/github-actions/ci.yml12
-rw-r--r--src/doc/rustc/book.toml3
-rw-r--r--src/doc/rustdoc/src/lints.md34
-rw-r--r--src/doc/unstable-book/src/language-features/lang-items.md311
-rw-r--r--src/doc/unstable-book/src/language-features/start.md59
-rw-r--r--src/librustdoc/clean/auto_trait.rs18
-rw-r--r--src/librustdoc/clean/blanket_impl.rs4
-rw-r--r--src/librustdoc/clean/cfg.rs28
-rw-r--r--src/librustdoc/clean/inline.rs6
-rw-r--r--src/librustdoc/clean/mod.rs8
-rw-r--r--src/librustdoc/clean/types.rs6
-rw-r--r--src/librustdoc/clean/utils.rs34
-rw-r--r--src/librustdoc/config.rs26
-rw-r--r--src/librustdoc/core.rs9
-rw-r--r--src/librustdoc/docfs.rs6
-rw-r--r--src/librustdoc/doctest.rs26
-rw-r--r--src/librustdoc/externalfiles.rs12
-rw-r--r--src/librustdoc/html/format.rs84
-rw-r--r--src/librustdoc/html/highlight.rs27
-rw-r--r--src/librustdoc/html/highlight/tests.rs2
-rw-r--r--src/librustdoc/html/length_limit.rs7
-rw-r--r--src/librustdoc/html/markdown.rs143
-rw-r--r--src/librustdoc/html/render/context.rs28
-rw-r--r--src/librustdoc/html/render/mod.rs23
-rw-r--r--src/librustdoc/html/render/print_item.rs108
-rw-r--r--src/librustdoc/html/render/sidebar.rs14
-rw-r--r--src/librustdoc/html/render/write_shared.rs21
-rw-r--r--src/librustdoc/html/sources.rs5
-rw-r--r--src/librustdoc/html/static_files.rs2
-rw-r--r--src/librustdoc/html/templates/STYLE.md2
-rw-r--r--src/librustdoc/json/mod.rs6
-rw-r--r--src/librustdoc/lib.rs12
-rw-r--r--src/librustdoc/lint.rs12
-rw-r--r--src/librustdoc/markdown.rs12
-rw-r--r--src/librustdoc/passes/calculate_doc_coverage.rs8
-rw-r--r--src/librustdoc/passes/check_doc_test_visibility.rs2
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs191
-rw-r--r--src/librustdoc/passes/lint.rs2
-rw-r--r--src/librustdoc/passes/lint/bare_urls.rs4
-rw-r--r--src/librustdoc/passes/lint/check_code_block_syntax.rs6
-rw-r--r--src/librustdoc/passes/lint/html_tags.rs10
-rw-r--r--src/librustdoc/passes/lint/redundant_explicit_links.rs352
-rw-r--r--src/librustdoc/scrape_examples.rs6
-rw-r--r--src/librustdoc/visit_ast.rs6
m---------src/llvm-project0
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs103
-rw-r--r--src/tools/clippy/clippy_lints/src/useless_conversion.rs18
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs4
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-11065.rs19
-rw-r--r--src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs35
-rw-r--r--src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr14
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.fixed14
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.rs14
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.stderr20
-rw-r--r--src/tools/compiletest/src/runtest.rs17
-rw-r--r--src/tools/miri/src/machine.rs19
-rw-r--r--src/tools/miri/src/shims/intrinsics/mod.rs16
-rw-r--r--src/tools/miri/src/shims/panic.rs19
-rw-r--r--src/tools/miri/tests/fail/breakpoint.rs2
-rw-r--r--src/tools/miri/tests/fail/breakpoint.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs4
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr6
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr6
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs4
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs4
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr6
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr6
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr27
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr27
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr2
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs7
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs2
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs6
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stderr8
-rw-r--r--src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr22
-rw-r--r--src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs7
-rw-r--r--src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr22
-rw-r--r--src/tools/miri/tests/fail/panic/double_panic.rs3
-rw-r--r--src/tools/miri/tests/fail/panic/double_panic.stderr24
-rw-r--r--src/tools/miri/tests/fail/terminate-terminator.rs8
-rw-r--r--src/tools/miri/tests/fail/terminate-terminator.stderr28
-rw-r--r--src/tools/miri/tests/fail/unwind-action-terminate.rs6
-rw-r--r--src/tools/miri/tests/fail/unwind-action-terminate.stderr26
-rw-r--r--src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs2
-rw-r--r--src/version2
-rw-r--r--tests/codegen/issues/issue-114312.rs27
-rw-r--r--tests/codegen/slice-ref-equality.rs32
-rw-r--r--tests/codegen/trailing_zeros.rs22
-rw-r--r--tests/mir-opt/basic_assignment.main.ElaborateDrops.diff10
-rw-r--r--tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir2
-rw-r--r--tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir2
-rw-r--r--tests/mir-opt/building/custom/terminators.rs4
-rw-r--r--tests/mir-opt/copy-prop/borrowed_local.rs4
-rw-r--r--tests/mir-opt/copy-prop/custom_move_arg.rs4
-rw-r--r--tests/mir-opt/copy-prop/move_projection.rs4
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff11
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff11
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir5
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir5
-rw-r--r--tests/mir-opt/issue_41110.test.ElaborateDrops.panic-abort.diff13
-rw-r--r--tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff13
-rw-r--r--tests/mir-opt/issue_41888.main.ElaborateDrops.panic-abort.diff38
-rw-r--r--tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff38
-rw-r--r--tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff22
-rw-r--r--tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff22
-rw-r--r--tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir5
-rw-r--r--tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir5
-rw-r--r--tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir7
-rw-r--r--tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir3
-rw-r--r--tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir93
-rw-r--r--tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir109
-rw-r--r--tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir109
-rw-r--r--tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir10
-rw-r--r--tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir10
-rw-r--r--tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir234
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir128
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir128
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir15
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir15
-rw-r--r--tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff59
-rw-r--r--tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff9
-rw-r--r--tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff51
-rw-r--r--tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff68
-rw-r--r--tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff51
-rw-r--r--tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff51
-rw-r--r--tests/mir-opt/reference_prop.rs10
-rw-r--r--tests/run-coverage-rustdoc/doctest.coverage216
-rw-r--r--tests/run-coverage/abort.coverage132
-rw-r--r--tests/run-coverage/assert.coverage64
-rw-r--r--tests/run-coverage/async.coverage256
-rw-r--r--tests/run-coverage/async2.coverage210
-rw-r--r--tests/run-coverage/closure.coverage430
-rw-r--r--tests/run-coverage/closure_macro.coverage80
-rw-r--r--tests/run-coverage/closure_macro_async.coverage162
-rw-r--r--tests/run-coverage/conditions.coverage174
-rw-r--r--tests/run-coverage/continue.coverage138
-rw-r--r--tests/run-coverage/dead_code.coverage74
-rw-r--r--tests/run-coverage/drop_trait.coverage66
-rw-r--r--tests/run-coverage/generator.coverage60
-rw-r--r--tests/run-coverage/generics.coverage120
-rw-r--r--tests/run-coverage/if.coverage56
-rw-r--r--tests/run-coverage/if_else.coverage80
-rw-r--r--tests/run-coverage/inline-dead.coverage54
-rw-r--r--tests/run-coverage/inline.coverage102
-rw-r--r--tests/run-coverage/inner_items.coverage114
-rw-r--r--tests/run-coverage/issue-83601.coverage28
-rw-r--r--tests/run-coverage/issue-84561.coverage364
-rw-r--r--tests/run-coverage/issue-85461.coverage64
-rw-r--r--tests/run-coverage/issue-93054.coverage56
-rw-r--r--tests/run-coverage/lazy_boolean.coverage122
-rw-r--r--tests/run-coverage/loop_break_value.coverage26
-rw-r--r--tests/run-coverage/loops_branches.coverage122
-rw-r--r--tests/run-coverage/match_or_pattern.coverage90
-rw-r--r--tests/run-coverage/nested_loops.coverage50
-rw-r--r--tests/run-coverage/no_cov_crate.coverage172
-rw-r--r--tests/run-coverage/overflow.coverage126
-rw-r--r--tests/run-coverage/panic_unwind.coverage62
-rw-r--r--tests/run-coverage/partial_eq.coverage92
-rw-r--r--tests/run-coverage/simple_loop.coverage70
-rw-r--r--tests/run-coverage/simple_match.coverage86
-rw-r--r--tests/run-coverage/sort_groups.coverage76
-rw-r--r--tests/run-coverage/test_harness.coverage20
-rw-r--r--tests/run-coverage/tight_inf_loop.coverage10
-rw-r--r--tests/run-coverage/try_error_result.coverage236
-rw-r--r--tests/run-coverage/unused.coverage106
-rw-r--r--tests/run-coverage/unused_mod.coverage18
-rw-r--r--tests/run-coverage/uses_crate.coverage286
-rw-r--r--tests/run-coverage/uses_inline_crate.coverage272
-rw-r--r--tests/run-coverage/while.coverage10
-rw-r--r--tests/run-coverage/while_early_ret.coverage84
-rw-r--r--tests/run-coverage/yield.coverage74
-rw-r--r--tests/run-make/doctests-keep-binaries/Makefile13
-rw-r--r--tests/run-make/doctests-runtool/Makefile20
-rw-r--r--tests/run-make/doctests-runtool/runtool.rs3
-rw-r--r--tests/run-make/doctests-runtool/t.rs11
-rw-r--r--tests/run-make/optimization-remarks-dir-pgo/Makefile1
-rw-r--r--tests/run-make/panic-abort-eh_frame/Makefile2
-rw-r--r--tests/run-make/panic-abort-eh_frame/foo.rs24
-rw-r--r--tests/rustdoc-gui/docblock-table.goml16
-rw-r--r--tests/rustdoc-gui/search-form-elements.goml386
-rw-r--r--tests/rustdoc-ui/lints/inline-doc-link.rs13
-rw-r--r--tests/rustdoc-ui/lints/no-redundancy.rs7
-rw-r--r--tests/rustdoc-ui/lints/redundant_explicit_links.fixed158
-rw-r--r--tests/rustdoc-ui/lints/redundant_explicit_links.rs158
-rw-r--r--tests/rustdoc-ui/lints/redundant_explicit_links.stderr1007
-rw-r--r--tests/rustdoc-ui/unescaped_backticks.rs1
-rw-r--r--tests/rustdoc-ui/unescaped_backticks.stderr128
-rw-r--r--tests/rustdoc/description.rs1
-rw-r--r--tests/rustdoc/intra-doc/basic.rs2
-rw-r--r--tests/rustdoc/intra-doc/generic-params.rs1
-rw-r--r--tests/rustdoc/intra-doc/issue-108459.rs1
-rw-r--r--tests/ui/abi/relocation_model_pic.rs9
-rw-r--r--tests/ui/argument-suggestions/extra_arguments.rs26
-rw-r--r--tests/ui/argument-suggestions/extra_arguments.stderr148
-rw-r--r--tests/ui/associated-type-bounds/consts.rs10
-rw-r--r--tests/ui/associated-type-bounds/consts.stderr10
-rw-r--r--tests/ui/associated-types/dont-suggest-cyclic-constraint.fixed13
-rw-r--r--tests/ui/associated-types/dont-suggest-cyclic-constraint.rs2
-rw-r--r--tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr6
-rw-r--r--tests/ui/async-await/deep-futures-are-freeze.rs179
-rw-r--r--tests/ui/async-await/normalize-output-in-signature-deduction.rs19
-rw-r--r--tests/ui/consts/assert-type-intrinsics.stderr6
-rw-r--r--tests/ui/feature-gates/feature-gate-cfg-relocation-model.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-cfg-relocation-model.stderr12
-rw-r--r--tests/ui/inference/str-as-char.fixed1
-rw-r--r--tests/ui/inference/str-as-char.rs1
-rw-r--r--tests/ui/inference/str-as-char.stderr13
-rw-r--r--tests/ui/inline-const/required-const.rs13
-rw-r--r--tests/ui/inline-const/required-const.stderr11
-rw-r--r--tests/ui/issues/issue-48364.stderr1
-rw-r--r--tests/ui/lint/reference_casting.rs29
-rw-r--r--tests/ui/lint/reference_casting.stderr90
-rw-r--r--tests/ui/macros/macro-interpolation.rs4
-rw-r--r--tests/ui/macros/macro-interpolation.stderr16
-rw-r--r--tests/ui/macros/rfc-3086-metavar-expr/issue-111904.rs14
-rw-r--r--tests/ui/macros/rfc-3086-metavar-expr/issue-111904.stderr19
-rw-r--r--tests/ui/match/issue-114691.rs39
-rw-r--r--tests/ui/mir/debug-ref-undef.rs57
-rw-r--r--tests/ui/or-patterns/missing-bindings.stderr68
-rw-r--r--tests/ui/parser/trait-object-delimiters.rs4
-rw-r--r--tests/ui/parser/trait-object-delimiters.stderr12
-rw-r--r--tests/ui/resolve/resolve-inconsistent-names.stderr18
-rw-r--r--tests/ui/span/issue-39698.stderr20
-rw-r--r--tests/ui/suggestions/copied-and-cloned.fixed18
-rw-r--r--tests/ui/suggestions/copied-and-cloned.rs16
-rw-r--r--tests/ui/suggestions/copied-and-cloned.stderr37
-rw-r--r--tests/ui/suggestions/issue-114701.rs15
-rw-r--r--tests/ui/suggestions/issue-114701.stderr15
-rw-r--r--tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed17
-rw-r--r--tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs17
-rw-r--r--tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.stderr38
-rw-r--r--tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-1.rs73
-rw-r--r--tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs75
-rw-r--r--tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr9
-rw-r--r--tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.rs19
-rw-r--r--tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.stderr11
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr20
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-1.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-2.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-2.stderr37
-rw-r--r--triagebot.toml3
412 files changed, 10491 insertions, 6720 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b55ab229811..3680136d89f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -323,17 +323,6 @@ jobs:
               NO_DEBUG_ASSERTIONS: 1
               NO_OVERFLOW_CHECKS: 1
             os: macos-13
-          - name: dist-x86_64-apple-alt
-            env:
-              SCRIPT: "./x.py dist bootstrap --include-default-paths"
-              RUST_CONFIGURE_ARGS: "--enable-extended --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.7
-              SELECT_XCODE: /Applications/Xcode_13.4.1.app
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              NO_OVERFLOW_CHECKS: 1
-            os: macos-13
           - name: x86_64-apple-1
             env:
               SCRIPT: "./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc --skip tests/run-make-fulldeps"
diff --git a/Cargo.lock b/Cargo.lock
index 8d707067bb9..266f34e69ed 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -167,9 +167,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.71"
+version = "1.0.75"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
+checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
 dependencies = [
  "backtrace",
 ]
@@ -5126,9 +5126,9 @@ checksum = "aac81b6fd6beb5884b0cf3321b8117e6e5d47ecb6fc89f414cfdcca8b2fe2dd8"
 
 [[package]]
 name = "thiserror"
-version = "1.0.40"
+version = "1.0.47"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
+checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f"
 dependencies = [
  "thiserror-impl",
 ]
@@ -5155,9 +5155,9 @@ dependencies = [
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.40"
+version = "1.0.47"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
+checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b"
 dependencies = [
  "proc-macro2",
  "quote",
diff --git a/RELEASES.md b/RELEASES.md
index e8c79c573f9..722f7e5dd08 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,108 @@
+Version 1.72.0 (2023-08-24)
+==========================
+
+<a id="1.72.0-Language"></a>
+
+Language
+--------
+
+- [Replace const eval limit by a lint and add an exponential backoff warning](https://github.com/rust-lang/rust/pull/103877/)
+- [expand: Change how `#![cfg(FALSE)]` behaves on crate root](https://github.com/rust-lang/rust/pull/110141/)
+- [Stabilize inline asm for LoongArch64](https://github.com/rust-lang/rust/pull/111235/)
+- [Uplift `clippy::undropped_manually_drops` lint](https://github.com/rust-lang/rust/pull/111530/)
+- [Uplift `clippy::invalid_utf8_in_unchecked` lint](https://github.com/rust-lang/rust/pull/111543/)
+- [Uplift `clippy::cast_ref_to_mut` lint](https://github.com/rust-lang/rust/pull/111567/)
+- [Uplift `clippy::cmp_nan` lint](https://github.com/rust-lang/rust/pull/111818/)
+- [resolve: Remove artificial import ambiguity errors](https://github.com/rust-lang/rust/pull/112086/)
+- [Don't require associated types with Self: Sized bounds in `dyn Trait` objects](https://github.com/rust-lang/rust/pull/112319/)
+
+<a id="1.72.0-Compiler"></a>
+
+Compiler
+--------
+
+- [Remember names of `cfg`-ed out items to mention them in diagnostics](https://github.com/rust-lang/rust/pull/109005/)
+- [Support for native WASM exceptions](https://github.com/rust-lang/rust/pull/111322/)
+- [Add support for NetBSD/aarch64-be (big-endian arm64).](https://github.com/rust-lang/rust/pull/111326/)
+- [Write to stdout if `-` is given as output file](https://github.com/rust-lang/rust/pull/111626/)
+- [Force all native libraries to be statically linked when linking a static binary](https://github.com/rust-lang/rust/pull/111698/)
+- [Add Tier 3 support for `loongarch64-unknown-none*`](https://github.com/rust-lang/rust/pull/112310/)
+- [Prevent `.eh_frame` from being emitted for `-C panic=abort`](https://github.com/rust-lang/rust/pull/112403/)
+- [Support 128-bit enum variant in debuginfo codegen](https://github.com/rust-lang/rust/pull/112474/)
+- [compiler: update solaris/illumos to enable tsan support.](https://github.com/rust-lang/rust/pull/112039/)
+
+Refer to Rust's [platform support page][platform-support-doc]
+for more information on Rust's tiered platform support.
+
+<a id="1.72.0-Libraries"></a>
+
+Libraries
+---------
+
+- [Document memory orderings of `thread::{park, unpark}`](https://github.com/rust-lang/rust/pull/99587/)
+- [io: soften ‘at most one write attempt’ requirement in io::Write::write](https://github.com/rust-lang/rust/pull/107200/)
+- [Specify behavior of HashSet::insert](https://github.com/rust-lang/rust/pull/107619/)
+- [Relax implicit `T: Sized` bounds on `BufReader<T>`, `BufWriter<T>` and `LineWriter<T>`](https://github.com/rust-lang/rust/pull/111074/)
+- [Update runtime guarantee for `select_nth_unstable`](https://github.com/rust-lang/rust/pull/111974/)
+- [Return `Ok` on kill if process has already exited](https://github.com/rust-lang/rust/pull/112594/)
+- [Implement PartialOrd for `Vec`s over different allocators](https://github.com/rust-lang/rust/pull/112632/)
+- [Use 128 bits for TypeId hash](https://github.com/rust-lang/rust/pull/109953/)
+- [Don't drain-on-drop in DrainFilter impls of various collections.](https://github.com/rust-lang/rust/pull/104455/)
+- [Make `{Arc,Rc,Weak}::ptr_eq` ignore pointer metadata](https://github.com/rust-lang/rust/pull/106450/)
+
+<a id="1.72.0-Rustdoc"></a>
+
+Rustdoc
+-------
+
+- [Allow whitespace as path separator like double colon](https://github.com/rust-lang/rust/pull/108537/)
+- [Add search result item types after their name](https://github.com/rust-lang/rust/pull/110688/)
+- [Search for slices and arrays by type with `[]`](https://github.com/rust-lang/rust/pull/111958/)
+- [Clean up type unification and "unboxing"](https://github.com/rust-lang/rust/pull/112233/)
+
+<a id="1.72.0-Stabilized-APIs"></a>
+
+Stabilized APIs
+---------------
+
+- [`impl<T: Send> Sync for mpsc::Sender<T>`](https://doc.rust-lang.org/nightly/std/sync/mpsc/struct.Sender.html#impl-Sync-for-Sender%3CT%3E)
+- [`impl TryFrom<&OsStr> for &str`](https://doc.rust-lang.org/nightly/std/primitive.str.html#impl-TryFrom%3C%26'a+OsStr%3E-for-%26'a+str)
+- [`String::leak`](https://doc.rust-lang.org/nightly/alloc/string/struct.String.html#method.leak)
+
+These APIs are now stable in const contexts:
+
+- [`CStr::from_bytes_with_nul`](https://doc.rust-lang.org/nightly/std/ffi/struct.CStr.html#method.from_bytes_with_nul)
+- [`CStr::to_bytes`](https://doc.rust-lang.org/nightly/std/ffi/struct.CStr.html#method.from_bytes_with_nul)
+- [`CStr::to_bytes_with_nul`](https://doc.rust-lang.org/nightly/std/ffi/struct.CStr.html#method.from_bytes_with_nul)
+- [`CStr::to_str`](https://doc.rust-lang.org/nightly/std/ffi/struct.CStr.html#method.from_bytes_with_nul)
+
+<a id="1.72.0-Cargo"></a>
+
+Cargo
+-----
+
+- Enable `-Zdoctest-in-workspace` by default. When running each documentation
+  test, the working directory is set to the root directory of the package the
+  test belongs to.
+  [docs](https://doc.rust-lang.org/nightly/cargo/commands/cargo-test.html#working-directory-of-tests)
+  [#12221](https://github.com/rust-lang/cargo/pull/12221)
+  [#12288](https://github.com/rust-lang/cargo/pull/12288)
+- Add support of the "default" keyword to reset previously set `build.jobs`
+  parallelism back to the default.
+  [#12222](https://github.com/rust-lang/cargo/pull/12222)
+
+<a id="1.72.0-Compatibility-Notes"></a>
+
+Compatibility Notes
+-------------------
+
+- [Alter `Display` for `Ipv6Addr` for IPv4-compatible addresses](https://github.com/rust-lang/rust/pull/112606/)
+- Cargo changed feature name validation check to a hard error. The warning was
+  added in Rust 1.49. These extended characters aren't allowed on crates.io, so
+  this should only impact users of other registries, or people who don't publish
+  to a registry.
+  [#12291](https://github.com/rust-lang/cargo/pull/12291)
+
 Version 1.71.0 (2023-07-13)
 ==========================
 
diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs
index f4900ece1cc..e45b7c154fa 100644
--- a/compiler/rustc_arena/src/lib.rs
+++ b/compiler/rustc_arena/src/lib.rs
@@ -11,6 +11,7 @@
     html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
     test(no_crate_inject, attr(deny(warnings)))
 )]
+#![feature(core_intrinsics)]
 #![feature(dropck_eyepatch)]
 #![feature(new_uninit)]
 #![feature(maybe_uninit_slice)]
@@ -30,11 +31,11 @@ use smallvec::SmallVec;
 
 use std::alloc::Layout;
 use std::cell::{Cell, RefCell};
-use std::cmp;
 use std::marker::PhantomData;
 use std::mem::{self, MaybeUninit};
 use std::ptr::{self, NonNull};
 use std::slice;
+use std::{cmp, intrinsics};
 
 #[inline(never)]
 #[cold]
@@ -363,6 +364,22 @@ unsafe impl<#[may_dangle] T> Drop for TypedArena<T> {
 
 unsafe impl<T: Send> Send for TypedArena<T> {}
 
+#[inline(always)]
+fn align_down(val: usize, align: usize) -> usize {
+    debug_assert!(align.is_power_of_two());
+    val & !(align - 1)
+}
+
+#[inline(always)]
+fn align_up(val: usize, align: usize) -> usize {
+    debug_assert!(align.is_power_of_two());
+    (val + align - 1) & !(align - 1)
+}
+
+// Pointer alignment is common in compiler types, so keep `DroplessArena` aligned to them
+// to optimize away alignment code.
+const DROPLESS_ALIGNMENT: usize = mem::align_of::<usize>();
+
 /// An arena that can hold objects of multiple different types that impl `Copy`
 /// and/or satisfy `!mem::needs_drop`.
 pub struct DroplessArena {
@@ -375,6 +392,8 @@ pub struct DroplessArena {
     /// start. (This is slightly simpler and faster than allocating upwards,
     /// see <https://fitzgeraldnick.com/2019/11/01/always-bump-downwards.html>.)
     /// When this pointer crosses the start pointer, a new chunk is allocated.
+    ///
+    /// This is kept aligned to DROPLESS_ALIGNMENT.
     end: Cell<*mut u8>,
 
     /// A vector of arena chunks.
@@ -395,9 +414,11 @@ impl Default for DroplessArena {
 }
 
 impl DroplessArena {
-    #[inline(never)]
-    #[cold]
-    fn grow(&self, additional: usize) {
+    fn grow(&self, layout: Layout) {
+        // Add some padding so we can align `self.end` while
+        // stilling fitting in a `layout` allocation.
+        let additional = layout.size() + cmp::max(DROPLESS_ALIGNMENT, layout.align()) - 1;
+
         unsafe {
             let mut chunks = self.chunks.borrow_mut();
             let mut new_cap;
@@ -416,13 +437,35 @@ impl DroplessArena {
             // Also ensure that this chunk can fit `additional`.
             new_cap = cmp::max(additional, new_cap);
 
-            let mut chunk = ArenaChunk::new(new_cap);
+            let mut chunk = ArenaChunk::new(align_up(new_cap, PAGE));
             self.start.set(chunk.start());
-            self.end.set(chunk.end());
+
+            // Align the end to DROPLESS_ALIGNMENT
+            let end = align_down(chunk.end().addr(), DROPLESS_ALIGNMENT);
+
+            // Make sure we don't go past `start`. This should not happen since the allocation
+            // should be at least DROPLESS_ALIGNMENT - 1 bytes.
+            debug_assert!(chunk.start().addr() <= end);
+
+            self.end.set(chunk.end().with_addr(end));
+
             chunks.push(chunk);
         }
     }
 
+    #[inline(never)]
+    #[cold]
+    fn grow_and_alloc_raw(&self, layout: Layout) -> *mut u8 {
+        self.grow(layout);
+        self.alloc_raw_without_grow(layout).unwrap()
+    }
+
+    #[inline(never)]
+    #[cold]
+    fn grow_and_alloc<T>(&self) -> *mut u8 {
+        self.grow_and_alloc_raw(Layout::new::<T>())
+    }
+
     /// Allocates a byte slice with specified layout from the current memory
     /// chunk. Returns `None` if there is no free space left to satisfy the
     /// request.
@@ -432,12 +475,17 @@ impl DroplessArena {
         let old_end = self.end.get();
         let end = old_end.addr();
 
-        let align = layout.align();
-        let bytes = layout.size();
+        // Align allocated bytes so that `self.end` stays aligned to DROPLESS_ALIGNMENT
+        let bytes = align_up(layout.size(), DROPLESS_ALIGNMENT);
+
+        // Tell LLVM that `end` is aligned to DROPLESS_ALIGNMENT
+        unsafe { intrinsics::assume(end == align_down(end, DROPLESS_ALIGNMENT)) };
 
-        let new_end = end.checked_sub(bytes)? & !(align - 1);
+        let new_end = align_down(end.checked_sub(bytes)?, layout.align());
         if start <= new_end {
             let new_end = old_end.with_addr(new_end);
+            // `new_end` is aligned to DROPLESS_ALIGNMENT as `align_down` preserves alignment
+            // as both `end` and `bytes` are already aligned to DROPLESS_ALIGNMENT.
             self.end.set(new_end);
             Some(new_end)
         } else {
@@ -448,21 +496,26 @@ impl DroplessArena {
     #[inline]
     pub fn alloc_raw(&self, layout: Layout) -> *mut u8 {
         assert!(layout.size() != 0);
-        loop {
-            if let Some(a) = self.alloc_raw_without_grow(layout) {
-                break a;
-            }
-            // No free space left. Allocate a new chunk to satisfy the request.
-            // On failure the grow will panic or abort.
-            self.grow(layout.size());
+        if let Some(a) = self.alloc_raw_without_grow(layout) {
+            return a;
         }
+        // No free space left. Allocate a new chunk to satisfy the request.
+        // On failure the grow will panic or abort.
+        self.grow_and_alloc_raw(layout)
     }
 
     #[inline]
     pub fn alloc<T>(&self, object: T) -> &mut T {
         assert!(!mem::needs_drop::<T>());
+        assert!(mem::size_of::<T>() != 0);
 
-        let mem = self.alloc_raw(Layout::for_value::<T>(&object)) as *mut T;
+        let mem = if let Some(a) = self.alloc_raw_without_grow(Layout::for_value::<T>(&object)) {
+            a
+        } else {
+            // No free space left. Allocate a new chunk to satisfy the request.
+            // On failure the grow will panic or abort.
+            self.grow_and_alloc::<T>()
+        } as *mut T;
 
         unsafe {
             // Write into uninitialized memory.
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index bae3979fbf9..48e9b180b74 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -13,6 +13,7 @@ use crate::tokenstream::*;
 use crate::{ast::*, StaticItem};
 
 use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
+use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_data_structures::sync::Lrc;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::Ident;
@@ -1369,7 +1370,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
         ExprKind::If(cond, tr, fl) => {
             vis.visit_expr(cond);
             vis.visit_block(tr);
-            visit_opt(fl, |fl| vis.visit_expr(fl));
+            visit_opt(fl, |fl| ensure_sufficient_stack(|| vis.visit_expr(fl)));
         }
         ExprKind::While(cond, body, label) => {
             vis.visit_expr(cond);
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 068b255e9f2..58ce73047bc 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -150,6 +150,8 @@ pub fn print_crate<'a>(
 /// and also addresses some specific regressions described in #63896 and #73345.
 fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool {
     if let TokenTree::Token(token, _) = prev {
+        // No space after these tokens, e.g. `x.y`, `$e`
+        // (The carets point to `prev`.)       ^     ^
         if matches!(token.kind, token::Dot | token::Dollar) {
             return false;
         }
@@ -158,10 +160,19 @@ fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool {
         }
     }
     match tt {
+        // No space before these tokens, e.g. `foo,`, `println!`, `x.y`
+        // (The carets point to `token`.)         ^           ^     ^
+        //
+        // FIXME: having `Not` here works well for macro invocations like
+        // `println!()`, but is bad when `!` means "logical not" or "the never
+        // type", where the lack of space causes ugliness like this:
+        // `Fn() ->!`, `x =! y`, `if! x { f(); }`.
         TokenTree::Token(token, _) => !matches!(token.kind, token::Comma | token::Not | token::Dot),
+        // No space before parentheses if preceded by these tokens, e.g. `foo(...)`
         TokenTree::Delimited(_, Delimiter::Parenthesis, _) => {
             !matches!(prev, TokenTree::Token(Token { kind: token::Ident(..), .. }, _))
         }
+        // No space before brackets if preceded by these tokens, e.g. `#[...]`
         TokenTree::Delimited(_, Delimiter::Bracket, _) => {
             !matches!(prev, TokenTree::Token(Token { kind: token::Pound, .. }, _))
         }
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs
index d257145373f..becfa535a59 100644
--- a/compiler/rustc_borrowck/src/consumers.rs
+++ b/compiler/rustc_borrowck/src/consumers.rs
@@ -30,7 +30,7 @@ pub use super::{
 /// will be retrieved.
 #[derive(Debug, Copy, Clone)]
 pub enum ConsumerOptions {
-    /// Retrieve the [`Body`] along with the [`BorrowSet`](super::borrow_set::BorrowSet)
+    /// Retrieve the [`Body`] along with the [`BorrowSet`]
     /// and [`RegionInferenceContext`]. If you would like the body only, use
     /// [`TyCtxt::mir_promoted`].
     ///
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index 1e89a9f5144..4ac633c263f 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -2,12 +2,14 @@
 #![deny(rustc::diagnostic_outside_of_impl)]
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_index::bit_set::BitSet;
-use rustc_middle::mir::{self, BasicBlock, Body, Location, Place};
+use rustc_middle::mir::{
+    self, BasicBlock, Body, CallReturnPlaces, Location, Place, TerminatorEdges,
+};
 use rustc_middle::ty::RegionVid;
 use rustc_middle::ty::TyCtxt;
 use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces};
 use rustc_mir_dataflow::ResultsVisitable;
-use rustc_mir_dataflow::{self, fmt::DebugWithContext, CallReturnPlaces, GenKill};
+use rustc_mir_dataflow::{self, fmt::DebugWithContext, GenKill};
 use rustc_mir_dataflow::{Analysis, Direction, Results};
 use std::fmt;
 
@@ -334,6 +336,10 @@ impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> {
 impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
     type Idx = BorrowIndex;
 
+    fn domain_size(&self, _: &mir::Body<'tcx>) -> usize {
+        self.borrow_set.len()
+    }
+
     fn before_statement_effect(
         &mut self,
         trans: &mut impl GenKill<Self::Idx>,
@@ -400,12 +406,12 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
         self.kill_loans_out_of_scope_at_location(trans, location);
     }
 
-    fn terminator_effect(
+    fn terminator_effect<'mir>(
         &mut self,
-        trans: &mut impl GenKill<Self::Idx>,
-        terminator: &mir::Terminator<'tcx>,
+        trans: &mut Self::Domain,
+        terminator: &'mir mir::Terminator<'tcx>,
         _location: Location,
-    ) {
+    ) -> TerminatorEdges<'mir, 'tcx> {
         if let mir::TerminatorKind::InlineAsm { operands, .. } = &terminator.kind {
             for op in operands {
                 if let mir::InlineAsmOperand::Out { place: Some(place), .. }
@@ -415,6 +421,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
                 }
             }
         }
+        terminator.edges()
     }
 
     fn call_return_effect(
diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs
index df5e383ad40..d4c42a75874 100644
--- a/compiler/rustc_borrowck/src/invalidation.rs
+++ b/compiler/rustc_borrowck/src/invalidation.rs
@@ -159,7 +159,9 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
 
                 self.mutate_place(location, *resume_arg, Deep);
             }
-            TerminatorKind::Resume | TerminatorKind::Return | TerminatorKind::GeneratorDrop => {
+            TerminatorKind::UnwindResume
+            | TerminatorKind::Return
+            | TerminatorKind::GeneratorDrop => {
                 // Invalidate all borrows of local places
                 let borrow_set = self.borrow_set;
                 let start = self.location_table.start_index(location);
@@ -200,7 +202,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
                 }
             }
             TerminatorKind::Goto { target: _ }
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindTerminate
             | 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 efe525c224d..ef2788efbcf 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -770,9 +770,9 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
             }
 
             TerminatorKind::Goto { target: _ }
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Unreachable
-            | TerminatorKind::Resume
+            | TerminatorKind::UnwindResume
             | TerminatorKind::Return
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ }
@@ -803,7 +803,9 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
                 }
             }
 
-            TerminatorKind::Resume | TerminatorKind::Return | TerminatorKind::GeneratorDrop => {
+            TerminatorKind::UnwindResume
+            | TerminatorKind::Return
+            | TerminatorKind::GeneratorDrop => {
                 // Returning from the function implicitly kills storage for all locals and statics.
                 // Often, the storage will already have been killed by an explicit
                 // StorageDead, but we don't always emit those (notably on unwind paths),
@@ -815,7 +817,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
                 }
             }
 
-            TerminatorKind::Terminate
+            TerminatorKind::UnwindTerminate
             | 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 50d875dfae9..d91a3d94045 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1333,8 +1333,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         debug!("terminator kind: {:?}", term.kind);
         match &term.kind {
             TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Return
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Unreachable
@@ -1608,12 +1608,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     self.assert_iscleanup(body, block_data, *target, is_cleanup);
                 }
             }
-            TerminatorKind::Resume => {
+            TerminatorKind::UnwindResume => {
                 if !is_cleanup {
                     span_mirbug!(self, block_data, "resume on non-cleanup block!")
                 }
             }
-            TerminatorKind::Terminate => {
+            TerminatorKind::UnwindTerminate => {
                 if !is_cleanup {
                     span_mirbug!(self, block_data, "abort on non-cleanup block!")
                 }
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 522dd7189fe..ed371a04c53 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -474,10 +474,10 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
                     *destination,
                 );
             }
-            TerminatorKind::Terminate => {
+            TerminatorKind::UnwindTerminate => {
                 codegen_panic_cannot_unwind(fx, source_info);
             }
-            TerminatorKind::Resume => {
+            TerminatorKind::UnwindResume => {
                 // FIXME implement unwinding
                 fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
             }
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index c3153574295..7db5f79eead 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -550,8 +550,8 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
                 match &bb_data.terminator().kind {
                     TerminatorKind::Goto { .. }
                     | TerminatorKind::SwitchInt { .. }
-                    | TerminatorKind::Resume
-                    | TerminatorKind::Terminate
+                    | TerminatorKind::UnwindResume
+                    | TerminatorKind::UnwindTerminate
                     | TerminatorKind::Return
                     | TerminatorKind::Unreachable
                     | TerminatorKind::Drop { .. }
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 4c9094bf1f5..b6c01545f30 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -128,7 +128,10 @@ fn instrument_function_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'ll Attr
 
         // The function name varies on platforms.
         // See test/CodeGen/mcount.c in clang.
-        let mcount_name = cx.sess().target.mcount.as_ref();
+        let mcount_name = match &cx.sess().target.llvm_mcount_intrinsic {
+            Some(llvm_mcount_intrinsic) => llvm_mcount_intrinsic.as_ref(),
+            None => cx.sess().target.mcount.as_ref(),
+        };
 
         attrs.push(llvm::CreateAttrStringValue(
             cx.llcx,
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 0be84c9fa83..4c854740753 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -16,6 +16,7 @@ use rustc_metadata::fs::METADATA_FILENAME;
 use rustc_metadata::EncodedMetadata;
 use rustc_session::cstore::MetadataLoader;
 use rustc_session::Session;
+use rustc_span::sym;
 use rustc_target::abi::Endian;
 use rustc_target::spec::{ef_avr_arch, RelocModel, Target};
 
@@ -272,35 +273,38 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
         Architecture::Riscv32 | Architecture::Riscv64 => {
             // Source: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/079772828bd10933d34121117a222b4cc0ee2200/riscv-elf.adoc
             let mut e_flags: u32 = 0x0;
-            let features = &sess.target.options.features;
+
             // Check if compressed is enabled
-            if features.contains("+c") {
+            // `unstable_target_features` is used here because "c" is gated behind riscv_target_feature.
+            if sess.unstable_target_features.contains(&sym::c) {
                 e_flags |= elf::EF_RISCV_RVC;
             }
 
-            // Select the appropriate floating-point ABI
-            if features.contains("+d") {
-                e_flags |= elf::EF_RISCV_FLOAT_ABI_DOUBLE;
-            } else if features.contains("+f") {
-                e_flags |= elf::EF_RISCV_FLOAT_ABI_SINGLE;
-            } else {
-                e_flags |= elf::EF_RISCV_FLOAT_ABI_SOFT;
+            // Set the appropriate flag based on ABI
+            // This needs to match LLVM `RISCVELFStreamer.cpp`
+            match &*sess.target.llvm_abiname {
+                "" | "ilp32" | "lp64" => (),
+                "ilp32f" | "lp64f" => e_flags |= elf::EF_RISCV_FLOAT_ABI_SINGLE,
+                "ilp32d" | "lp64d" => e_flags |= elf::EF_RISCV_FLOAT_ABI_DOUBLE,
+                "ilp32e" => e_flags |= elf::EF_RISCV_RVE,
+                _ => bug!("unknown RISC-V ABI name"),
             }
+
             e_flags
         }
         Architecture::LoongArch64 => {
             // Source: https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc#e_flags-identifies-abi-type-and-version
             let mut e_flags: u32 = elf::EF_LARCH_OBJABI_V1;
-            let features = &sess.target.options.features;
 
-            // Select the appropriate floating-point ABI
-            if features.contains("+d") {
-                e_flags |= elf::EF_LARCH_ABI_DOUBLE_FLOAT;
-            } else if features.contains("+f") {
-                e_flags |= elf::EF_LARCH_ABI_SINGLE_FLOAT;
-            } else {
-                e_flags |= elf::EF_LARCH_ABI_SOFT_FLOAT;
+            // Set the appropriate flag based on ABI
+            // This needs to match LLVM `LoongArchELFStreamer.cpp`
+            match &*sess.target.llvm_abiname {
+                "ilp32s" | "lp64s" => e_flags |= elf::EF_LARCH_ABI_SOFT_FLOAT,
+                "ilp32f" | "lp64f" => e_flags |= elf::EF_LARCH_ABI_SINGLE_FLOAT,
+                "ilp32d" | "lp64d" => e_flags |= elf::EF_LARCH_ABI_DOUBLE_FLOAT,
+                _ => bug!("unknown RISC-V ABI name"),
             }
+
             e_flags
         }
         Architecture::Avr => {
diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
index 22c1f05974d..3f5b46333d9 100644
--- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
@@ -284,8 +284,8 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKi
         for (bb, data) in mir.basic_blocks.iter_enumerated() {
             match data.terminator().kind {
                 TerminatorKind::Goto { .. }
-                | TerminatorKind::Resume
-                | TerminatorKind::Terminate
+                | TerminatorKind::UnwindResume
+                | TerminatorKind::UnwindTerminate
                 | TerminatorKind::Return
                 | TerminatorKind::GeneratorDrop
                 | TerminatorKind::Unreachable
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 4f26383ed05..19228183462 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1224,12 +1224,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
         self.set_debug_loc(bx, terminator.source_info);
         match terminator.kind {
-            mir::TerminatorKind::Resume => {
+            mir::TerminatorKind::UnwindResume => {
                 self.codegen_resume_terminator(helper, bx);
                 MergingSucc::False
             }
 
-            mir::TerminatorKind::Terminate => {
+            mir::TerminatorKind::UnwindTerminate => {
                 self.codegen_terminate_terminator(helper, bx, terminator);
                 MergingSucc::False
             }
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index 4167a85ccd5..564b5da32cc 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -42,9 +42,6 @@ pub struct PerLocalVarDebugInfo<'tcx, D> {
 
     /// `.place.projection` from `mir::VarDebugInfo`.
     pub projection: &'tcx ty::List<mir::PlaceElem<'tcx>>,
-
-    /// `references` from `mir::VarDebugInfo`.
-    pub references: u8,
 }
 
 #[derive(Clone, Copy, Debug)]
@@ -323,7 +320,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     dbg_var,
                     fragment: None,
                     projection: ty::List::empty(),
-                    references: 0,
                 })
             }
         } else {
@@ -399,15 +395,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         &self,
         bx: &mut Bx,
         local: mir::Local,
-        mut base: PlaceRef<'tcx, Bx::Value>,
+        base: PlaceRef<'tcx, Bx::Value>,
         var: PerLocalVarDebugInfo<'tcx, Bx::DIVariable>,
     ) {
         let Some(dbg_var) = var.dbg_var else { return };
         let Some(dbg_loc) = self.dbg_loc(var.source_info) else { return };
 
-        let DebugInfoOffset { mut direct_offset, indirect_offsets, result: _ } =
+        let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
             calculate_debuginfo_offset(bx, local, &var, base.layout);
-        let mut indirect_offsets = &indirect_offsets[..];
 
         // When targeting MSVC, create extra allocas for arguments instead of pointing multiple
         // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
@@ -421,9 +416,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             // LLVM can handle simple things but anything more complex than just a direct
             // offset or one indirect offset of 0 is too complex for it to generate CV records
             // correctly.
-            && (direct_offset != Size::ZERO || !matches!(indirect_offsets, [Size::ZERO] | []));
+            && (direct_offset != Size::ZERO || !matches!(&indirect_offsets[..], [Size::ZERO] | []));
+
+        if should_create_individual_allocas {
+            let DebugInfoOffset { direct_offset: _, indirect_offsets: _, result: place } =
+                calculate_debuginfo_offset(bx, local, &var, base);
 
-        let create_alloca = |bx: &mut Bx, place: PlaceRef<'tcx, Bx::Value>, refcount| {
             // Create a variable which will be a pointer to the actual value
             let ptr_ty = Ty::new_ptr(
                 bx.tcx(),
@@ -431,35 +429,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             );
             let ptr_layout = bx.layout_of(ptr_ty);
             let alloca = PlaceRef::alloca(bx, ptr_layout);
-            bx.set_var_name(alloca.llval, &format!("{}.ref{}.dbg.spill", var.name, refcount));
+            bx.set_var_name(alloca.llval, &(var.name.to_string() + ".dbg.spill"));
 
             // Write the pointer to the variable
             bx.store(place.llval, alloca.llval, alloca.align);
 
             // Point the debug info to `*alloca` for the current variable
-            alloca
-        };
-
-        if var.references > 0 {
-            base = calculate_debuginfo_offset(bx, local, &var, base).result;
-
-            // Point the debug info to `&...&base == alloca` for the current variable
-            for refcount in 0..var.references {
-                base = create_alloca(bx, base, refcount);
-            }
-
-            direct_offset = Size::ZERO;
-            indirect_offsets = &[];
-        } else if should_create_individual_allocas {
-            let place = calculate_debuginfo_offset(bx, local, &var, base).result;
-
-            // Point the debug info to `*alloca` for the current variable
-            base = create_alloca(bx, place, 0);
-            direct_offset = Size::ZERO;
-            indirect_offsets = &[Size::ZERO];
+            bx.dbg_var_addr(dbg_var, dbg_loc, alloca.llval, Size::ZERO, &[Size::ZERO], None);
+        } else {
+            bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, &indirect_offsets, None);
         }
-
-        bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, indirect_offsets, None);
     }
 
     pub fn debug_introduce_locals(&self, bx: &mut Bx) {
@@ -492,7 +471,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             };
 
             let dbg_var = dbg_scope_and_span.map(|(dbg_scope, _, span)| {
-                let (mut var_ty, var_kind) = match var.value {
+                let (var_ty, var_kind) = match var.value {
                     mir::VarDebugInfoContents::Place(place) => {
                         let var_ty = self.monomorphized_place_ty(place.as_ref());
                         let var_kind = if let Some(arg_index) = var.argument_index
@@ -529,13 +508,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     }
                 };
 
-                for _ in 0..var.references {
-                    var_ty = Ty::new_ptr(
-                        bx.tcx(),
-                        ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: var_ty },
-                    );
-                }
-
                 self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span)
             });
 
@@ -547,7 +519,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         dbg_var,
                         fragment: None,
                         projection: place.projection,
-                        references: var.references,
                     });
                 }
                 mir::VarDebugInfoContents::Const(c) => {
@@ -601,7 +572,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                 Some(fragment_start..fragment_start + fragment_layout.size)
                             },
                             projection: place.projection,
-                            references: var.references,
                         });
                     }
                 }
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index d39a7e8a192..f146b93ff0c 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -18,7 +18,6 @@ pub enum ConstEvalErrKind {
     ModifiedGlobal,
     AssertFailure(AssertKind<ConstInt>),
     Panic { msg: Symbol, line: u32, col: u32, file: Symbol },
-    Abort(String),
 }
 
 impl MachineStopType for ConstEvalErrKind {
@@ -30,7 +29,6 @@ impl MachineStopType for ConstEvalErrKind {
             ModifiedGlobal => const_eval_modified_global,
             Panic { .. } => const_eval_panic,
             AssertFailure(x) => x.diagnostic_message(),
-            Abort(msg) => msg.to_string().into(),
         }
     }
     fn add_args(
@@ -39,7 +37,7 @@ impl MachineStopType for ConstEvalErrKind {
     ) {
         use ConstEvalErrKind::*;
         match *self {
-            ConstAccessesStatic | ModifiedGlobal | Abort(_) => {}
+            ConstAccessesStatic | ModifiedGlobal => {}
             AssertFailure(kind) => kind.add_args(adder),
             Panic { msg, line, col, file } => {
                 adder("msg".into(), msg.into_diagnostic_arg());
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 032f4be6c99..f16aea6f34b 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -427,52 +427,48 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
 
     fn find_mir_or_eval_fn(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
-        instance: ty::Instance<'tcx>,
+        orig_instance: ty::Instance<'tcx>,
         _abi: CallAbi,
         args: &[FnArg<'tcx>],
         dest: &PlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
         _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);
+        debug!("find_mir_or_eval_fn: {:?}", orig_instance);
+
+        // Replace some functions.
+        let Some(instance) = ecx.hook_special_const_fn(orig_instance, args, dest, ret)? else {
+            // Call has already been handled.
+            return Ok(None);
+        };
 
         // Only check non-glue functions
         if let ty::InstanceDef::Item(def) = instance.def {
             // Execution might have wandered off into other crates, so we cannot do a stability-
-            // sensitive check here. But we can at least rule out functions that are not const
-            // at all.
-            if !ecx.tcx.is_const_fn_raw(def) {
-                // allow calling functions inside a trait marked with #[const_trait].
-                if !ecx.tcx.is_const_default_method(def) {
-                    // We certainly do *not* want to actually call the fn
-                    // though, so be sure we return here.
-                    throw_unsup_format!("calling non-const function `{}`", instance)
-                }
-            }
-
-            let Some(new_instance) = ecx.hook_special_const_fn(instance, args, dest, ret)? else {
-                return Ok(None);
-            };
-
-            if new_instance != instance {
-                // We call another const fn instead.
-                // However, we return the *original* instance to make backtraces work out
-                // (and we hope this does not confuse the FnAbi checks too much).
-                return Ok(Self::find_mir_or_eval_fn(
-                    ecx,
-                    new_instance,
-                    _abi,
-                    args,
-                    dest,
-                    ret,
-                    _unwind,
-                )?
-                .map(|(body, _instance)| (body, instance)));
+            // sensitive check here. But we can at least rule out functions that are not const at
+            // all. That said, we have to allow calling functions inside a trait marked with
+            // #[const_trait]. These *are* const-checked!
+            // FIXME: why does `is_const_fn_raw` not classify them as const?
+            if (!ecx.tcx.is_const_fn_raw(def) && !ecx.tcx.is_const_default_method(def))
+                || ecx.tcx.has_attr(def, sym::rustc_do_not_const_check)
+            {
+                // We certainly do *not* want to actually call the fn
+                // though, so be sure we return here.
+                throw_unsup_format!("calling non-const function `{}`", instance)
             }
         }
 
         // This is a const fn. Call it.
-        Ok(Some((ecx.load_mir(instance.def, None)?, instance)))
+        // In case of replacement, we return the *original* instance to make backtraces work out
+        // (and we hope this does not confuse the FnAbi checks too much).
+        Ok(Some((ecx.load_mir(instance.def, None)?, orig_instance)))
+    }
+
+    fn panic_nounwind(ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &str) -> InterpResult<'tcx> {
+        let msg = Symbol::intern(msg);
+        let span = ecx.find_closest_untracked_caller_location();
+        let (file, line, col) = ecx.location_triple_for_span(span);
+        Err(ConstEvalErrKind::Panic { msg, file, line, col }.into())
     }
 
     fn call_intrinsic(
@@ -595,10 +591,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         Err(ConstEvalErrKind::AssertFailure(err).into())
     }
 
-    fn abort(_ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: String) -> InterpResult<'tcx, !> {
-        Err(ConstEvalErrKind::Abort(msg).into())
-    }
-
     fn binary_ptr_op(
         _ecx: &InterpCx<'mir, 'tcx, Self>,
         _bin_op: mir::BinOp,
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 3ac6f07e8b7..61d3de5c405 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -765,7 +765,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
             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())?;
+                M::unwind_terminate(self)?;
+                // This might have pushed a new stack frame, or it terminated execution.
+                // Either way, `loc` will not be updated.
+                return Ok(());
             }
         };
         Ok(())
@@ -865,6 +868,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     panic!("encountered StackPopCleanup::Root when unwinding!")
                 }
             };
+            // This must be the very last thing that happens, since it can in fact push a new stack frame.
             self.unwind_to_block(unwind)
         } else {
             // Follow the normal return edge.
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index f22cd919c36..d6ca6fe73a6 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -125,15 +125,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     ) -> InterpResult<'tcx, bool> {
         let instance_args = instance.args;
         let intrinsic_name = self.tcx.item_name(instance.def_id());
-
-        // First handle intrinsics without return place.
-        let ret = match ret {
-            None => match intrinsic_name {
-                sym::abort => M::abort(self, "the program aborted execution".to_owned())?,
-                // Unsupported diverging intrinsic.
-                _ => return Ok(false),
-            },
-            Some(p) => p,
+        let Some(ret) = ret else {
+            // We don't support any intrinsic without return place.
+            return Ok(false);
         };
 
         match intrinsic_name {
@@ -410,7 +404,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         ValidityRequirement::Uninit => bug!("assert_uninit_valid doesn't exist"),
                     };
 
-                    M::abort(self, msg)?;
+                    M::panic_nounwind(self, &msg)?;
+                    // Skip the `go_to_block` at the end.
+                    return Ok(true);
                 }
             }
             sym::simd_insert => {
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index e101785b6e2..d3c73b896c0 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -218,10 +218,11 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx>;
 
-    /// Called to abort evaluation.
-    fn abort(_ecx: &mut InterpCx<'mir, 'tcx, Self>, _msg: String) -> InterpResult<'tcx, !> {
-        throw_unsup_format!("aborting execution is not supported")
-    }
+    /// Called to trigger a non-unwinding panic.
+    fn panic_nounwind(_ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &str) -> InterpResult<'tcx>;
+
+    /// Called when unwinding reached a state where execution should be terminated.
+    fn unwind_terminate(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>;
 
     /// Called for all binary operations where the LHS has pointer type.
     ///
@@ -500,6 +501,11 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
     }
 
     #[inline(always)]
+    fn unwind_terminate(_ecx: &mut InterpCx<$mir, $tcx, Self>) -> InterpResult<$tcx> {
+        unreachable!("unwinding cannot happen during compile-time evaluation")
+    }
+
+    #[inline(always)]
     fn call_extra_fn(
         _ecx: &mut InterpCx<$mir, $tcx, Self>,
         fn_val: !,
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 3c03172bbef..b2ebcceceb3 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -196,15 +196,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 }
             }
 
-            Terminate => {
-                // FIXME: maybe should call `panic_no_unwind` lang item instead.
-                M::abort(self, "panic in a function that cannot unwind".to_owned())?;
+            UnwindTerminate => {
+                M::unwind_terminate(self)?;
             }
 
             // When we encounter Resume, we've finished unwinding
             // cleanup for the current stack frame. We pop it in order
             // to continue unwinding the next frame
-            Resume => {
+            UnwindResume => {
                 trace!("unwinding: resuming from cleanup");
                 // By definition, a Resume terminator means
                 // that we're unwinding
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 fae047bff9e..e67098a3ac3 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -1037,7 +1037,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                 self.check_op(ops::Generator(hir::GeneratorKind::Gen))
             }
 
-            TerminatorKind::Terminate => {
+            TerminatorKind::UnwindTerminate => {
                 // Cleanup blocks are skipped for const checking (see `visit_basic_block_data`).
                 span_bug!(self.span, "`Terminate` terminator outside of cleanup block")
             }
@@ -1046,7 +1046,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
             | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. }
             | TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
+            | TerminatorKind::UnwindResume
             | TerminatorKind::Return
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::Unreachable => {}
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 e3377bd10c6..a8c61d2c8fd 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
@@ -106,7 +106,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
                 }
             }
 
-            mir::TerminatorKind::Terminate
+            mir::TerminatorKind::UnwindTerminate
             | mir::TerminatorKind::Call { .. }
             | mir::TerminatorKind::Assert { .. }
             | mir::TerminatorKind::FalseEdge { .. }
@@ -114,7 +114,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
             | mir::TerminatorKind::GeneratorDrop
             | mir::TerminatorKind::Goto { .. }
             | mir::TerminatorKind::InlineAsm { .. }
-            | mir::TerminatorKind::Resume
+            | mir::TerminatorKind::UnwindResume
             | mir::TerminatorKind::Return
             | mir::TerminatorKind::SwitchInt { .. }
             | mir::TerminatorKind::Unreachable
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs
index 3a869f7f547..a137f84b738 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs
@@ -4,10 +4,12 @@
 
 use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::visit::Visitor;
-use rustc_middle::mir::{self, BasicBlock, Local, Location, Statement, StatementKind};
+use rustc_middle::mir::{
+    self, BasicBlock, CallReturnPlaces, Local, Location, Statement, StatementKind, TerminatorEdges,
+};
 use rustc_mir_dataflow::fmt::DebugWithContext;
 use rustc_mir_dataflow::JoinSemiLattice;
-use rustc_mir_dataflow::{Analysis, AnalysisDomain, CallReturnPlaces};
+use rustc_mir_dataflow::{Analysis, AnalysisDomain};
 
 use std::fmt;
 use std::marker::PhantomData;
@@ -345,13 +347,14 @@ where
         self.transfer_function(state).visit_statement(statement, location);
     }
 
-    fn apply_terminator_effect(
+    fn apply_terminator_effect<'mir>(
         &mut self,
         state: &mut Self::Domain,
-        terminator: &mir::Terminator<'tcx>,
+        terminator: &'mir mir::Terminator<'tcx>,
         location: Location,
-    ) {
+    ) -> TerminatorEdges<'mir, 'tcx> {
         self.transfer_function(state).visit_terminator(terminator, location);
+        terminator.edges()
     }
 
     fn apply_call_return_effect(
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 83004492c8b..0dfbbf73dce 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -18,6 +18,7 @@ use rustc_mir_dataflow::impls::MaybeStorageLive;
 use rustc_mir_dataflow::storage::always_storage_live_locals;
 use rustc_mir_dataflow::{Analysis, ResultsCursor};
 use rustc_target::abi::{Size, FIRST_VARIANT};
+use rustc_target::spec::abi::Abi;
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 enum EdgeKind {
@@ -58,6 +59,25 @@ impl<'tcx> MirPass<'tcx> for Validator {
             .iterate_to_fixpoint()
             .into_results_cursor(body);
 
+        let can_unwind = if mir_phase <= MirPhase::Runtime(RuntimePhase::Initial) {
+            // In this case `AbortUnwindingCalls` haven't yet been executed.
+            true
+        } else if !tcx.def_kind(def_id).is_fn_like() {
+            true
+        } else {
+            let body_ty = tcx.type_of(def_id).skip_binder();
+            let body_abi = match body_ty.kind() {
+                ty::FnDef(..) => body_ty.fn_sig(tcx).abi(),
+                ty::Closure(..) => Abi::RustCall,
+                ty::Generator(..) => Abi::Rust,
+                _ => {
+                    span_bug!(body.span, "unexpected body ty: {:?} phase {:?}", body_ty, mir_phase)
+                }
+            };
+
+            ty::layout::fn_can_unwind(tcx, Some(def_id), body_abi)
+        };
+
         let mut cfg_checker = CfgChecker {
             when: &self.when,
             body,
@@ -68,6 +88,7 @@ impl<'tcx> MirPass<'tcx> for Validator {
             storage_liveness,
             place_cache: FxHashSet::default(),
             value_cache: FxHashSet::default(),
+            can_unwind,
         };
         cfg_checker.visit_body(body);
         cfg_checker.check_cleanup_control_flow();
@@ -99,6 +120,9 @@ struct CfgChecker<'a, 'tcx> {
     storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive<'static>>,
     place_cache: FxHashSet<PlaceRef<'tcx>>,
     value_cache: FxHashSet<u128>,
+    // If `false`, then the MIR must not contain `UnwindAction::Continue` or
+    // `TerminatorKind::Resume`.
+    can_unwind: bool,
 }
 
 impl<'a, 'tcx> CfgChecker<'a, 'tcx> {
@@ -237,13 +261,17 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> {
         match unwind {
             UnwindAction::Cleanup(unwind) => {
                 if is_cleanup {
-                    self.fail(location, "unwind on cleanup block");
+                    self.fail(location, "`UnwindAction::Cleanup` in cleanup block");
                 }
                 self.check_edge(location, unwind, EdgeKind::Unwind);
             }
             UnwindAction::Continue => {
                 if is_cleanup {
-                    self.fail(location, "unwind on cleanup block");
+                    self.fail(location, "`UnwindAction::Continue` in cleanup block");
+                }
+
+                if !self.can_unwind {
+                    self.fail(location, "`UnwindAction::Continue` in no-unwind function");
                 }
             }
             UnwindAction::Unreachable | UnwindAction::Terminate => (),
@@ -464,13 +492,19 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
                     );
                 }
             }
-            TerminatorKind::Resume | TerminatorKind::Terminate => {
+            TerminatorKind::UnwindResume => {
                 let bb = location.block;
                 if !self.body.basic_blocks[bb].is_cleanup {
-                    self.fail(
-                        location,
-                        "Cannot `Resume` or `Terminate` from non-cleanup basic block",
-                    )
+                    self.fail(location, "Cannot `UnwindResume` from non-cleanup basic block")
+                }
+                if !self.can_unwind {
+                    self.fail(location, "Cannot `UnwindResume` in a function that cannot unwind")
+                }
+            }
+            TerminatorKind::UnwindTerminate => {
+                let bb = location.block;
+                if !self.body.basic_blocks[bb].is_cleanup {
+                    self.fail(location, "Cannot `UnwindTerminate` from non-cleanup basic block")
                 }
             }
             TerminatorKind::Return => {
@@ -665,7 +699,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                                 return;
                             };
 
-                            f_ty.ty
+                            ty::EarlyBinder::bind(f_ty.ty).instantiate(self.tcx, args)
                         } else {
                             let Some(&f_ty) = args.as_generator().prefix_tys().get(f.index())
                             else {
@@ -701,12 +735,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             VarDebugInfoContents::Const(_) => {}
             VarDebugInfoContents::Place(place) => {
                 check_place(self, place);
-                if debuginfo.references != 0 && place.projection.last() == Some(&PlaceElem::Deref) {
-                    self.fail(
-                        START_BLOCK.start_location(),
-                        format!("debuginfo {debuginfo:?}, has both ref and deref"),
-                    );
-                }
             }
             VarDebugInfoContents::Composite { ty, ref fragments } => {
                 for f in fragments {
@@ -1204,8 +1232,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             | TerminatorKind::FalseUnwind { .. }
             | TerminatorKind::InlineAsm { .. }
             | TerminatorKind::GeneratorDrop
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable => {}
         }
diff --git a/compiler/rustc_error_codes/src/error_codes/E0132.md b/compiler/rustc_error_codes/src/error_codes/E0132.md
index a23cc988bdb..51258739b89 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0132.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0132.md
@@ -13,7 +13,7 @@ It is not possible to declare type parameters on a function that has the `start`
 attribute. Such a function must have the following type signature (for more
 information, view [the unstable book][1]):
 
-[1]: https://doc.rust-lang.org/unstable-book/language-features/lang-items.html#writing-an-executable-without-stdlib
+[1]: https://doc.rust-lang.org/unstable-book/language-features/start.html
 
 ```
 # let _:
diff --git a/compiler/rustc_error_codes/src/error_codes/E0152.md b/compiler/rustc_error_codes/src/error_codes/E0152.md
index ef17b8b4c75..d862766571d 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0152.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0152.md
@@ -20,6 +20,6 @@ attributes:
 #![no_std]
 ```
 
-See also the [unstable book][1].
+See also [this section of the Rustonomicon][beneath std].
 
-[1]: https://doc.rust-lang.org/unstable-book/language-features/lang-items.html#writing-an-executable-without-stdlib
+[beneath std]: https://doc.rust-lang.org/nomicon/beneath-std.html
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 7d660d2dbaa..34518b53759 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -452,11 +452,11 @@ struct HandlerInner {
     /// have been converted.
     check_unstable_expect_diagnostics: bool,
 
-    /// Expected [`Diagnostic`][diagnostic::Diagnostic]s store a [`LintExpectationId`] as part of
+    /// Expected [`Diagnostic`][struct@diagnostic::Diagnostic]s store a [`LintExpectationId`] as part of
     /// the lint level. [`LintExpectationId`]s created early during the compilation
     /// (before `HirId`s have been defined) are not stable and can therefore not be
     /// stored on disk. This buffer stores these diagnostics until the ID has been
-    /// replaced by a stable [`LintExpectationId`]. The [`Diagnostic`][diagnostic::Diagnostic]s are the
+    /// replaced by a stable [`LintExpectationId`]. The [`Diagnostic`][struct@diagnostic::Diagnostic]s are the
     /// submitted for storage and added to the list of fulfilled expectations.
     unstable_expect_diagnostics: Vec<Diagnostic>,
 
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index 05c0cd952b8..7e85beaadcb 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -81,7 +81,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::ErrorGuaranteed;
 use rustc_lint_defs::pluralize;
-use rustc_parse::parser::{NtOrTt, Parser};
+use rustc_parse::parser::{ParseNtResult, Parser};
 use rustc_span::symbol::Ident;
 use rustc_span::symbol::MacroRulesNormalizedIdent;
 use rustc_span::Span;
@@ -692,8 +692,8 @@ impl TtParser {
                             Ok(nt) => nt,
                         };
                         let m = match nt {
-                            NtOrTt::Nt(nt) => MatchedNonterminal(Lrc::new(nt)),
-                            NtOrTt::Tt(tt) => MatchedTokenTree(tt),
+                            ParseNtResult::Nt(nt) => MatchedNonterminal(Lrc::new(nt)),
+                            ParseNtResult::Tt(tt) => MatchedTokenTree(tt),
                         };
                         mp.push_match(next_metavar, seq_depth, m);
                         mp.idx += 1;
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index ce8b4621720..a5959d68fbc 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -1328,7 +1328,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
                     _ => IsInFollow::No(TOKENS),
                 }
             }
-            NonterminalKind::PatWithOr { .. } => {
+            NonterminalKind::PatWithOr => {
                 const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`if`", "`in`"];
                 match tok {
                     TokenTree::Token(token) => match token.kind {
diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs
index b6382dcb894..7c37aadc67a 100644
--- a/compiler/rustc_expand/src/mbe/metavar_expr.rs
+++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs
@@ -93,7 +93,17 @@ fn parse_count<'sess>(
     span: Span,
 ) -> PResult<'sess, MetaVarExpr> {
     let ident = parse_ident(iter, sess, span)?;
-    let depth = if try_eat_comma(iter) { Some(parse_depth(iter, sess, span)?) } else { None };
+    let depth = if try_eat_comma(iter) {
+        if iter.look_ahead(0).is_none() {
+            return Err(sess.span_diagnostic.struct_span_err(
+                span,
+                "`count` followed by a comma must have an associated index indicating its depth",
+            ));
+        }
+        Some(parse_depth(iter, sess, span)?)
+    } else {
+        None
+    };
     Ok(MetaVarExpr::Count(ident, depth))
 }
 
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index a5f83b88f7e..15e7ab3fe3e 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -220,16 +220,15 @@ pub(super) fn transcribe<'a>(
                         MatchedTokenTree(tt) => {
                             // `tt`s are emitted into the output stream directly as "raw tokens",
                             // without wrapping them into groups.
-                            let token = tt.clone();
-                            result.push(token);
+                            result.push(tt.clone());
                         }
                         MatchedNonterminal(nt) => {
                             // Other variables are emitted into the output stream as groups with
                             // `Delimiter::Invisible` to maintain parsing priorities.
                             // `Interpolated` is currently used for such groups in rustc parser.
                             marker.visit_span(&mut sp);
-                            let token = TokenTree::token_alone(token::Interpolated(nt.clone()), sp);
-                            result.push(token);
+                            result
+                                .push(TokenTree::token_alone(token::Interpolated(nt.clone()), sp));
                         }
                         MatchedSeq(..) => {
                             // We were unable to descend far enough. This is an error.
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 953ea1bf523..f5708f933d5 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -352,6 +352,8 @@ declare_features! (
     (active, c_variadic, "1.34.0", Some(44930), None),
     /// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour.
     (active, cfg_overflow_checks, "1.71.0", Some(111466), None),
+    /// Provides the relocation model information as cfg entry
+    (active, cfg_relocation_model, "CURRENT_RUSTC_VERSION", Some(114929), None),
     /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
     (active, cfg_sanitize, "1.41.0", Some(39699), None),
     /// Allows `cfg(target_abi = "...")`.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index a183cfd8776..2f7cff3ce5c 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -35,6 +35,7 @@ const GATED_CFGS: &[GatedCfg] = &[
     (sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
     (sym::sanitize, sym::cfg_sanitize, cfg_fn!(cfg_sanitize)),
     (sym::version, sym::cfg_version, cfg_fn!(cfg_version)),
+    (sym::relocation_model, sym::cfg_relocation_model, cfg_fn!(cfg_relocation_model)),
 ];
 
 /// Find a gated cfg determined by the `pred`icate which is given the cfg's name.
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 166760166c1..597cae6ff33 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -1,6 +1,9 @@
 hir_analysis_ambiguous_lifetime_bound =
     ambiguous lifetime bound, explicit lifetime bound required
 
+hir_analysis_assoc_bound_on_const = expected associated type, found {$descr}
+    .note = trait bounds not allowed on {$descr}
+
 hir_analysis_assoc_type_binding_not_allowed =
     associated type bindings are not allowed here
     .label = associated type not allowed here
diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
index 30145b1a185..ba152cd48de 100644
--- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
@@ -13,7 +13,7 @@ use crate::astconv::{
     AstConv, ConvertedBinding, ConvertedBindingKind, OnlySelfBounds, PredicateFilter,
 };
 use crate::bounds::Bounds;
-use crate::errors::{MultipleRelaxedDefaultBounds, ValueOfAssociatedStructAlreadySpecified};
+use crate::errors;
 
 impl<'tcx> dyn AstConv<'tcx> + '_ {
     /// Sets `implicitly_sized` to true on `Bounds` if necessary
@@ -35,7 +35,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
                     if unbound.is_none() {
                         unbound = Some(&ptr.trait_ref);
                     } else {
-                        tcx.sess.emit_err(MultipleRelaxedDefaultBounds { span });
+                        tcx.sess.emit_err(errors::MultipleRelaxedDefaultBounds { span });
                     }
                 }
             }
@@ -326,7 +326,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
             dup_bindings
                 .entry(assoc_item.def_id)
                 .and_modify(|prev_span| {
-                    tcx.sess.emit_err(ValueOfAssociatedStructAlreadySpecified {
+                    tcx.sess.emit_err(errors::ValueOfAssociatedStructAlreadySpecified {
                         span: binding.span,
                         prev_span: *prev_span,
                         item_name: binding.item_name,
@@ -488,6 +488,8 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
             }
         }
 
+        let assoc_item_def_id = projection_ty.skip_binder().def_id;
+        let def_kind = tcx.def_kind(assoc_item_def_id);
         match binding.kind {
             ConvertedBindingKind::Equality(..) if return_type_notation => {
                 return Err(self.tcx().sess.emit_err(
@@ -499,11 +501,9 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
                 // the "projection predicate" for:
                 //
                 // `<T as Iterator>::Item = u32`
-                let assoc_item_def_id = projection_ty.skip_binder().def_id;
-                let def_kind = tcx.def_kind(assoc_item_def_id);
                 match (def_kind, term.unpack()) {
-                    (hir::def::DefKind::AssocTy, ty::TermKind::Ty(_))
-                    | (hir::def::DefKind::AssocConst, ty::TermKind::Const(_)) => (),
+                    (DefKind::AssocTy, ty::TermKind::Ty(_))
+                    | (DefKind::AssocConst, ty::TermKind::Const(_)) => (),
                     (_, _) => {
                         let got = if let Some(_) = term.ty() { "type" } else { "constant" };
                         let expected = tcx.def_descr(assoc_item_def_id);
@@ -516,7 +516,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
                             format!("{expected} defined here"),
                         );
 
-                        if let hir::def::DefKind::AssocConst = def_kind
+                        if let DefKind::AssocConst = def_kind
                           && let Some(t) = term.ty() && (t.is_enum() || t.references_error())
                           && tcx.features().associated_const_equality {
                             err.span_suggestion(
@@ -528,8 +528,8 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
                         }
                         let reported = err.emit();
                         term = match def_kind {
-                            hir::def::DefKind::AssocTy => Ty::new_error(tcx, reported).into(),
-                            hir::def::DefKind::AssocConst => ty::Const::new_error(
+                            DefKind::AssocTy => Ty::new_error(tcx, reported).into(),
+                            DefKind::AssocConst => ty::Const::new_error(
                                 tcx,
                                 reported,
                                 tcx.type_of(assoc_item_def_id)
@@ -548,6 +548,15 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
                 );
             }
             ConvertedBindingKind::Constraint(ast_bounds) => {
+                match def_kind {
+                    DefKind::AssocTy => {}
+                    _ => {
+                        return Err(tcx.sess.emit_err(errors::AssocBoundOnConst {
+                            span: assoc_ident.span,
+                            descr: tcx.def_descr(assoc_item_def_id),
+                        }));
+                    }
+                }
                 // "Desugar" a constraint like `T: Iterator<Item: Debug>` to
                 //
                 // `<T as Iterator>::Item: Debug`
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 0babdf7e5b3..9471ad9ca90 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -918,3 +918,12 @@ pub struct UnusedAssociatedTypeBounds {
     #[suggestion(code = "")]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_assoc_bound_on_const)]
+#[note]
+pub struct AssocBoundOnConst {
+    #[primary_span]
+    pub span: Span,
+    pub descr: &'static str,
+}
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index dd79d1afc62..02371f85ac3 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -599,6 +599,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 = self.typeck_results.borrow().qpath_res(qpath, callee_expr.hir_id)
             // Only suggest removing parens if there are no arguments
             && arg_exprs.is_empty()
+            && call_expr.span.contains(callee_expr.span)
         {
             let descr = match kind {
                 def::CtorOf::Struct => "struct",
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 5bc0e2ee86c..31a03fabe4f 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -389,34 +389,26 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                 if let ty::Ref(reg, cast_ty, mutbl) = *self.cast_ty.kind() {
                     if let ty::RawPtr(TypeAndMut { ty: expr_ty, .. }) = *self.expr_ty.kind()
                         && fcx
-                            .try_coerce(
-                                self.expr,
+                            .can_coerce(
                                 Ty::new_ref(fcx.tcx,
                                     fcx.tcx.lifetimes.re_erased,
                                     TypeAndMut { ty: expr_ty, mutbl },
                                 ),
                                 self.cast_ty,
-                                AllowTwoPhase::No,
-                                None,
                             )
-                            .is_ok()
                     {
                         sugg = Some((format!("&{}*", mutbl.prefix_str()), cast_ty == expr_ty));
                     } else if let ty::Ref(expr_reg, expr_ty, expr_mutbl) = *self.expr_ty.kind()
                         && expr_mutbl == Mutability::Not
                         && mutbl == Mutability::Mut
                         && fcx
-                            .try_coerce(
-                                self.expr,
+                            .can_coerce(
                                 Ty::new_ref(fcx.tcx,
                                     expr_reg,
                                     TypeAndMut { ty: expr_ty, mutbl: Mutability::Mut },
                                 ),
                                 self.cast_ty,
-                                AllowTwoPhase::No,
-                                None,
                             )
-                            .is_ok()
                     {
                         sugg_mutref = true;
                     }
@@ -424,30 +416,22 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                     if !sugg_mutref
                         && sugg == None
                         && fcx
-                            .try_coerce(
-                                self.expr,
+                            .can_coerce(
                                 Ty::new_ref(fcx.tcx,reg, TypeAndMut { ty: self.expr_ty, mutbl }),
                                 self.cast_ty,
-                                AllowTwoPhase::No,
-                                None,
                             )
-                            .is_ok()
                     {
                         sugg = Some((format!("&{}", mutbl.prefix_str()), false));
                     }
                 } else if let ty::RawPtr(TypeAndMut { mutbl, .. }) = *self.cast_ty.kind()
                     && fcx
-                        .try_coerce(
-                            self.expr,
+                        .can_coerce(
                             Ty::new_ref(fcx.tcx,
                                 fcx.tcx.lifetimes.re_erased,
                                 TypeAndMut { ty: self.expr_ty, mutbl },
                             ),
                             self.cast_ty,
-                            AllowTwoPhase::No,
-                            None,
                         )
-                        .is_ok()
                 {
                     sugg = Some((format!("&{}", mutbl.prefix_str()), false));
                 }
@@ -760,7 +744,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                     ty::FnDef(..) => {
                         // Attempt a coercion to a fn pointer type.
                         let f = fcx.normalize(self.expr_span, self.expr_ty.fn_sig(fcx.tcx));
-                        let res = fcx.try_coerce(
+                        let res = fcx.coerce(
                             self.expr,
                             self.expr_ty,
                             Ty::new_fn_ptr(fcx.tcx, f),
@@ -860,7 +844,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
 
             (_, DynStar) => {
                 if fcx.tcx.features().dyn_star {
-                    bug!("should be handled by `try_coerce`")
+                    bug!("should be handled by `coerce`")
                 } else {
                     Err(CastError::IllegalCast)
                 }
@@ -956,7 +940,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
 
                 // Coerce to a raw pointer so that we generate AddressOf in MIR.
                 let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr);
-                fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None)
+                fcx.coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None)
                     .unwrap_or_else(|_| {
                         bug!(
                         "could not cast from reference to array to pointer to array ({:?} to {:?})",
@@ -992,7 +976,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
     }
 
     fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<(), ty::error::TypeError<'tcx>> {
-        match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No, None) {
+        match fcx.coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No, None) {
             Ok(_) => Ok(()),
             Err(err) => Err(err),
         }
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 3e67afb1c3d..b19fb6da6de 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -711,6 +711,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         };
 
+        let span = self.tcx.def_span(expr_def_id);
+
         let output_ty = match *ret_ty.kind() {
             ty::Infer(ty::TyVar(ret_vid)) => {
                 self.obligations_for_self_ty(ret_vid).find_map(|obligation| {
@@ -724,20 +726,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
             ty::Error(_) => return None,
             _ => span_bug!(
-                self.tcx.def_span(expr_def_id),
+                span,
                 "async fn generator return type not an inference variable: {ret_ty}"
             ),
         };
 
+        let output_ty = self.normalize(span, output_ty);
+
         // async fn that have opaque types in their return type need to redo the conversion to inference variables
         // as they fetch the still opaque version from the signature.
         let InferOk { value: output_ty, obligations } = self
-            .replace_opaque_types_with_inference_vars(
-                output_ty,
-                body_def_id,
-                self.tcx.def_span(expr_def_id),
-                self.param_env,
-            );
+            .replace_opaque_types_with_inference_vars(output_ty, body_def_id, span, self.param_env);
         self.register_predicates(obligations);
 
         Some(output_ty)
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 726914a995b..fca675ea9d8 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1005,7 +1005,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// adjusted type of the expression, if successful.
     /// Adjustments are only recorded if the coercion succeeded.
     /// The expressions *must not* have any preexisting adjustments.
-    pub fn try_coerce(
+    pub fn coerce(
         &self,
         expr: &hir::Expr<'_>,
         expr_ty: Ty<'tcx>,
@@ -1036,7 +1036,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         })
     }
 
-    /// Same as `try_coerce()`, but without side-effects.
+    /// Same as `coerce()`, but without side-effects.
     ///
     /// Returns false if the coercion creates any obligations that result in
     /// errors.
@@ -1494,7 +1494,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                 // Special-case the first expression we are coercing.
                 // To be honest, I'm not entirely sure why we do this.
                 // We don't allow two-phase borrows, see comment in try_find_coercion_lub for why
-                fcx.try_coerce(
+                fcx.coerce(
                     expression,
                     expression_ty,
                     self.expected_ty,
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 5b06088c348..2c16f21b491 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -53,7 +53,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             || self.suggest_no_capture_closure(err, expected, expr_ty)
             || self.suggest_boxing_when_appropriate(err, expr.span, expr.hir_id, expected, expr_ty)
             || self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected)
-            || self.suggest_copied_cloned_or_as_ref(err, expr, expr_ty, expected, expected_ty_expr)
+            || self.suggest_copied_cloned_or_as_ref(err, expr, expr_ty, expected)
             || self.suggest_clone_for_ref(err, expr, expr_ty, expected)
             || self.suggest_into(err, expr, expr_ty, expected)
             || self.suggest_floating_point_literal(err, expr, expected)
@@ -254,7 +254,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>) {
         let expected = self.resolve_vars_with_obligations(expected);
 
-        let e = match self.try_coerce(expr, checked_ty, expected, allow_two_phase, None) {
+        let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) {
             Ok(ty) => return (ty, None),
             Err(e) => e,
         };
@@ -475,7 +475,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 {
                     let Some(arg_ty) = self.node_ty_opt(arg_expr.hir_id) else { continue; };
                     let arg_ty = arg_ty.fold_with(&mut fudger);
-                    let _ = self.try_coerce(
+                    let _ = self.coerce(
                         arg_expr,
                         arg_ty,
                         *expected_arg_ty,
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 36096aa35d4..054d23c71d4 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -253,7 +253,7 @@ impl HelpUseLatestEdition {
 }
 
 #[derive(Subdiagnostic)]
-pub enum OptionResultRefMismatch<'tcx> {
+pub enum OptionResultRefMismatch {
     #[suggestion(
         hir_typeck_option_result_copied,
         code = ".copied()",
@@ -276,19 +276,20 @@ pub enum OptionResultRefMismatch<'tcx> {
         span: Span,
         def_path: String,
     },
-    #[suggestion(
-        hir_typeck_option_result_asref,
-        code = ".as_ref()",
-        style = "verbose",
-        applicability = "machine-applicable"
-    )]
-    AsRef {
-        #[primary_span]
-        span: Span,
-        def_path: String,
-        expected_ty: Ty<'tcx>,
-        expr_ty: Ty<'tcx>,
-    },
+    // FIXME: #114050
+    // #[suggestion(
+    //     hir_typeck_option_result_asref,
+    //     code = ".as_ref()",
+    //     style = "verbose",
+    //     applicability = "machine-applicable"
+    // )]
+    // AsRef {
+    //     #[primary_span]
+    //     span: Span,
+    //     def_path: String,
+    //     expected_ty: Ty<'tcx>,
+    //     expr_ty: Ty<'tcx>,
+    // },
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 817115012a4..4def7867384 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -260,9 +260,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // fulfillment error to be more accurate.
             let coerced_ty = self.resolve_vars_with_obligations(coerced_ty);
 
-            let coerce_error = self
-                .try_coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None)
-                .err();
+            let coerce_error =
+                self.coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None).err();
 
             if coerce_error.is_some() {
                 return Compatibility::Incompatible(coerce_error);
@@ -519,7 +518,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // suggestions and labels are (more) correct when an arg is a
         // macro invocation.
         let normalize_span = |span: Span| -> Span {
-            let normalized_span = span.find_ancestor_inside(error_span).unwrap_or(span);
+            let normalized_span = span.find_ancestor_inside_same_ctxt(error_span).unwrap_or(span);
             // Sometimes macros mess up the spans, so do not normalize the
             // arg span to equal the error span, because that's less useful
             // than pointing out the arg expr in the wrong context.
@@ -929,7 +928,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     };
                     labels.push((provided_span, format!("unexpected argument{provided_ty_name}")));
                     let mut span = provided_span;
-                    if span.can_be_used_for_suggestions() {
+                    if span.can_be_used_for_suggestions()
+                        && error_span.can_be_used_for_suggestions()
+                    {
                         if arg_idx.index() > 0
                         && let Some((_, prev)) = provided_arg_tys
                             .get(ProvidedIdx::from_usize(arg_idx.index() - 1)
@@ -1220,22 +1221,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
         if let Some(suggestion_text) = suggestion_text {
             let source_map = self.sess().source_map();
-            let (mut suggestion, suggestion_span) =
-                if let Some(call_span) = full_call_span.find_ancestor_inside(error_span) {
-                    ("(".to_string(), call_span.shrink_to_hi().to(error_span.shrink_to_hi()))
-                } else {
-                    (
-                        format!(
-                            "{}(",
-                            source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| {
-                                fn_def_id.map_or("".to_string(), |fn_def_id| {
-                                    tcx.item_name(fn_def_id).to_string()
-                                })
+            let (mut suggestion, suggestion_span) = if let Some(call_span) =
+                full_call_span.find_ancestor_inside_same_ctxt(error_span)
+            {
+                ("(".to_string(), call_span.shrink_to_hi().to(error_span.shrink_to_hi()))
+            } else {
+                (
+                    format!(
+                        "{}(",
+                        source_map.span_to_snippet(full_call_span).unwrap_or_else(|_| {
+                            fn_def_id.map_or("".to_string(), |fn_def_id| {
+                                tcx.item_name(fn_def_id).to_string()
                             })
-                        ),
-                        error_span,
-                    )
-                };
+                        })
+                    ),
+                    error_span,
+                )
+            };
             let mut needs_comma = false;
             for (expected_idx, provided_idx) in matched_inputs.iter_enumerated() {
                 if needs_comma {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 48358e338da..d2a53ee8b5e 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1097,7 +1097,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &hir::Expr<'_>,
         expr_ty: Ty<'tcx>,
         expected_ty: Ty<'tcx>,
-        expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
     ) -> bool {
         let ty::Adt(adt_def, args) = expr_ty.kind() else {
             return false;
@@ -1115,7 +1114,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         {
             let expr_inner_ty = args.type_at(0);
             let expected_inner_ty = expected_args.type_at(0);
-            if let &ty::Ref(_, ty, mutability) = expr_inner_ty.kind()
+            if let &ty::Ref(_, ty, _mutability) = expr_inner_ty.kind()
                     && self.can_eq(self.param_env, ty, expected_inner_ty)
                 {
                     let def_path = self.tcx.def_path_str(adt_def.did());
@@ -1124,14 +1123,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         errors::OptionResultRefMismatch::Copied {
                             span, def_path
                         }
-                    } else if let Some(expected_ty_expr) = expected_ty_expr
-                            // FIXME: suggest changes to both expressions to convert both to
-                            // Option/Result<&T>
-                            && mutability.is_not()
-                        {
-                        errors::OptionResultRefMismatch::AsRef {
-                            span: expected_ty_expr.span.shrink_to_hi(), expected_ty, expr_ty, def_path
-                        }
                     } else if let Some(clone_did) = self.tcx.lang_items().clone_trait()
                         && rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions(
                             self,
diff --git a/compiler/rustc_hir_typeck/src/method/prelude2021.rs b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
index 5b19a4c525f..3f1dca5b1de 100644
--- a/compiler/rustc_hir_typeck/src/method/prelude2021.rs
+++ b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
@@ -14,6 +14,7 @@ use rustc_span::symbol::kw::{Empty, Underscore};
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
 use rustc_trait_selection::infer::InferCtxtExt;
+use std::fmt::Write;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(super) fn lint_dot_call_from_2018(
@@ -143,16 +144,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                     let (self_adjusted, precise) = self.adjust_expr(pick, self_expr, sp);
                     if precise {
-                        let args = args
-                            .iter()
-                            .map(|arg| {
-                                let span = arg.span.find_ancestor_inside(sp).unwrap_or_default();
-                                format!(
-                                    ", {}",
-                                    self.sess().source_map().span_to_snippet(span).unwrap()
-                                )
-                            })
-                            .collect::<String>();
+                        let args = args.iter().fold(String::new(), |mut string, arg| {
+                            let span = arg.span.find_ancestor_inside(sp).unwrap_or_default();
+                            write!(
+                                string,
+                                ", {}",
+                                self.sess().source_map().span_to_snippet(span).unwrap()
+                            )
+                            .unwrap();
+                            string
+                        });
 
                         lint.span_suggestion(
                             sp,
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs
index 1111a1a17e2..db8ea2bfe48 100644
--- a/compiler/rustc_incremental/src/persist/fs.rs
+++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -538,9 +538,13 @@ where
             continue;
         }
 
-        let timestamp = extract_timestamp_from_session_dir(&directory_name).unwrap_or_else(|_| {
-            bug!("unexpected incr-comp session dir: {}", session_dir.display())
-        });
+        let timestamp = match extract_timestamp_from_session_dir(&directory_name) {
+            Ok(timestamp) => timestamp,
+            Err(e) => {
+                debug!("unexpected incr-comp session dir: {}: {}", session_dir.display(), e);
+                continue;
+            }
+        };
 
         if timestamp > best_candidate.0 {
             best_candidate = (timestamp, Some(session_dir.clone()));
@@ -562,14 +566,14 @@ fn is_session_directory_lock_file(file_name: &str) -> bool {
     file_name.starts_with("s-") && file_name.ends_with(LOCK_FILE_EXT)
 }
 
-fn extract_timestamp_from_session_dir(directory_name: &str) -> Result<SystemTime, ()> {
+fn extract_timestamp_from_session_dir(directory_name: &str) -> Result<SystemTime, &'static str> {
     if !is_session_directory(directory_name) {
-        return Err(());
+        return Err("not a directory");
     }
 
     let dash_indices: Vec<_> = directory_name.match_indices('-').map(|(idx, _)| idx).collect();
     if dash_indices.len() != 3 {
-        return Err(());
+        return Err("not three dashes in name");
     }
 
     string_to_timestamp(&directory_name[dash_indices[0] + 1..dash_indices[1]])
@@ -581,11 +585,11 @@ fn timestamp_to_string(timestamp: SystemTime) -> String {
     base_n::encode(micros as u128, INT_ENCODE_BASE)
 }
 
-fn string_to_timestamp(s: &str) -> Result<SystemTime, ()> {
+fn string_to_timestamp(s: &str) -> Result<SystemTime, &'static str> {
     let micros_since_unix_epoch = u64::from_str_radix(s, INT_ENCODE_BASE as u32);
 
     if micros_since_unix_epoch.is_err() {
-        return Err(());
+        return Err("timestamp not an int");
     }
 
     let micros_since_unix_epoch = micros_since_unix_epoch.unwrap();
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index dc41630196b..a5b2ccce85e 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -9,6 +9,7 @@ mod structural_impls;
 pub mod util;
 
 use std::cmp;
+use std::hash::{Hash, Hasher};
 
 use hir::def_id::LocalDefId;
 use rustc_hir as hir;
@@ -36,7 +37,7 @@ pub use rustc_middle::traits::*;
 /// either identifying an `impl` (e.g., `impl Eq for i32`) that
 /// satisfies the obligation, or else finding a bound that is in
 /// scope. The eventual result is usually a `Selection` (defined below).
-#[derive(Clone, PartialEq, Eq, Hash)]
+#[derive(Clone)]
 pub struct Obligation<'tcx, T> {
     /// The reason we have to prove this thing.
     pub cause: ObligationCause<'tcx>,
@@ -55,6 +56,27 @@ pub struct Obligation<'tcx, T> {
     pub recursion_depth: usize,
 }
 
+impl<'tcx, T: PartialEq> PartialEq<Obligation<'tcx, T>> for Obligation<'tcx, T> {
+    #[inline]
+    fn eq(&self, other: &Obligation<'tcx, T>) -> bool {
+        // Ignore `cause` and `recursion_depth`. This is a small performance
+        // win for a few crates, and a huge performance win for the crate in
+        // https://github.com/rust-lang/rustc-perf/pull/1680, which greatly
+        // stresses the trait system.
+        self.param_env == other.param_env && self.predicate == other.predicate
+    }
+}
+
+impl<T: Eq> Eq for Obligation<'_, T> {}
+
+impl<T: Hash> Hash for Obligation<'_, T> {
+    fn hash<H: Hasher>(&self, state: &mut H) -> () {
+        // See the comment on `Obligation::eq`.
+        self.param_env.hash(state);
+        self.predicate.hash(state);
+    }
+}
+
 impl<'tcx, P> From<Obligation<'tcx, P>> for solve::Goal<'tcx, P> {
     fn from(value: Obligation<'tcx, P>) -> Self {
         solve::Goal { param_env: value.param_env, predicate: value.predicate }
diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs
index 43f50a04aad..2577cabb3f0 100644
--- a/compiler/rustc_lint/src/reference_casting.rs
+++ b/compiler/rustc_lint/src/reference_casting.rs
@@ -100,7 +100,7 @@ fn is_cast_from_const_to_mut<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>)
 
     fn from_casts<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> {
         // <expr> as *mut ...
-        let e = if let ExprKind::Cast(e, t) = e.kind
+        let mut e = if let ExprKind::Cast(e, t) = e.kind
             && let ty::RawPtr(TypeAndMut { mutbl: Mutability::Mut, .. }) = cx.typeck_results().node_type(t.hir_id).kind() {
             e
         // <expr>.cast_mut()
@@ -112,23 +112,36 @@ fn is_cast_from_const_to_mut<'tcx>(cx: &LateContext<'tcx>, e: &'tcx Expr<'tcx>)
             return None;
         };
 
-        let e = e.peel_blocks();
-
-        // <expr> as *const ...
-        let e = if let ExprKind::Cast(e, t) = e.kind
-            && let ty::RawPtr(TypeAndMut { mutbl: Mutability::Not, .. }) = cx.typeck_results().node_type(t.hir_id).kind() {
-            e
-        // ptr::from_ref(<expr>)
-        } else if let ExprKind::Call(path, [arg]) = e.kind
-            && let ExprKind::Path(ref qpath) = path.kind
-            && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
-            && cx.tcx.is_diagnostic_item(sym::ptr_from_ref, def_id) {
-            arg
-        } else {
-            return None;
-        };
-
-        Some(e)
+        let mut had_at_least_one_cast = false;
+        loop {
+            e = e.peel_blocks();
+            // <expr> as *mut/const ... or <expr> as <uint>
+            e = if let ExprKind::Cast(expr, t) = e.kind
+                && matches!(cx.typeck_results().node_type(t.hir_id).kind(), ty::RawPtr(_) | ty::Uint(_))  {
+                had_at_least_one_cast = true;
+                expr
+            // <expr>.cast(), <expr>.cast_mut() or <expr>.cast_const()
+            } else if let ExprKind::MethodCall(_, expr, [], _) = e.kind
+                && let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
+                && matches!(
+                    cx.tcx.get_diagnostic_name(def_id),
+                    Some(sym::ptr_cast | sym::const_ptr_cast | sym::ptr_cast_mut | sym::ptr_cast_const)
+                )
+            {
+                had_at_least_one_cast = true;
+                expr
+            // ptr::from_ref(<expr>)
+            } else if let ExprKind::Call(path, [arg]) = e.kind
+                && let ExprKind::Path(ref qpath) = path.kind
+                && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
+                && cx.tcx.is_diagnostic_item(sym::ptr_from_ref, def_id) {
+                return Some(arg);
+            } else if had_at_least_one_cast {
+                return Some(e);
+            } else {
+                return None;
+            };
+        }
     }
 
     fn from_transmute<'tcx>(
diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs
index f1e7b8eb6c7..ba75517d7a6 100644
--- a/compiler/rustc_macros/src/serialize.rs
+++ b/compiler/rustc_macros/src/serialize.rs
@@ -59,14 +59,14 @@ fn decodable_body(
                 })
                 .collect();
             let message = format!(
-                "invalid enum variant tag while decoding `{}`, expected 0..{}",
+                "invalid enum variant tag while decoding `{}`, expected 0..{}, actual {{}}",
                 ty_name,
                 variants.len()
             );
             quote! {
                 match ::rustc_serialize::Decoder::read_usize(__decoder) {
                     #match_inner
-                    _ => panic!(#message),
+                    n => panic!(#message, n),
                 }
             }
         }
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index e8fd469e1fb..0da8fe9cca7 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -164,18 +164,15 @@ pub fn provide(providers: &mut Providers) {
         tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs)
     };
     providers.def_span = |tcx, def_id| {
-        let def_id = def_id;
         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
         tcx.hir().opt_span(hir_id).unwrap_or(DUMMY_SP)
     };
     providers.def_ident_span = |tcx, def_id| {
-        let def_id = def_id;
         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
         tcx.hir().opt_ident_span(hir_id)
     };
-    providers.fn_arg_names = |tcx, id| {
+    providers.fn_arg_names = |tcx, def_id| {
         let hir = tcx.hir();
-        let def_id = id;
         let hir_id = hir.local_def_id_to_hir_id(def_id);
         if let Some(body_id) = hir.maybe_body_owned_by(def_id) {
             tcx.arena.alloc_from_iter(hir.body_param_names(body_id))
@@ -190,7 +187,7 @@ pub fn provide(providers: &mut Providers) {
         {
             idents
         } else {
-            span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", id);
+            span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", def_id);
         }
     };
     providers.opt_def_kind = |tcx, def_id| tcx.hir().opt_def_kind(def_id);
diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs
index d7d6e3a0086..1efb54bdb08 100644
--- a/compiler/rustc_middle/src/mir/coverage.rs
+++ b/compiler/rustc_middle/src/mir/coverage.rs
@@ -96,21 +96,6 @@ pub enum CoverageKind {
     Unreachable,
 }
 
-impl CoverageKind {
-    pub fn as_operand(&self) -> Operand {
-        use CoverageKind::*;
-        match *self {
-            Counter { id, .. } => Operand::Counter(id),
-            Expression { id, .. } => Operand::Expression(id),
-            Unreachable => bug!("Unreachable coverage cannot be part of an expression"),
-        }
-    }
-
-    pub fn is_expression(&self) -> bool {
-        matches!(self, Self::Expression { .. })
-    }
-}
-
 impl Debug for CoverageKind {
     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
         use CoverageKind::*;
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index ddb5e248cdc..9ef3a1b30e4 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1109,10 +1109,6 @@ pub struct VarDebugInfo<'tcx> {
     /// originated from (starting from 1). Note, if MIR inlining is enabled, then this is the
     /// argument number in the original function before it was inlined.
     pub argument_index: Option<u16>,
-
-    /// The data represents `name` dereferenced `references` times,
-    /// and not the direct value.
-    pub references: u8,
 }
 
 ///////////////////////////////////////////////////////////////////////////
diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs
index c4c3341f873..cd74a403ff6 100644
--- a/compiler/rustc_middle/src/mir/patch.rs
+++ b/compiler/rustc_middle/src/mir/patch.rs
@@ -35,7 +35,7 @@ impl<'tcx> MirPatch<'tcx> {
 
         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() {
+            if let TerminatorKind::UnwindResume = block.terminator().kind && block.statements.is_empty() {
                 result.resume_block = Some(bb);
                 continue;
             }
@@ -50,7 +50,7 @@ impl<'tcx> MirPatch<'tcx> {
             }
 
             // Check if we already have a terminate block
-            if let TerminatorKind::Terminate = block.terminator().kind && block.statements.is_empty() {
+            if let TerminatorKind::UnwindTerminate = block.terminator().kind && block.statements.is_empty() {
                 result.terminate_block = Some(bb);
                 continue;
             }
@@ -68,7 +68,7 @@ impl<'tcx> MirPatch<'tcx> {
             statements: vec![],
             terminator: Some(Terminator {
                 source_info: SourceInfo::outermost(self.body_span),
-                kind: TerminatorKind::Resume,
+                kind: TerminatorKind::UnwindResume,
             }),
             is_cleanup: true,
         });
@@ -102,7 +102,7 @@ impl<'tcx> MirPatch<'tcx> {
             statements: vec![],
             terminator: Some(Terminator {
                 source_info: SourceInfo::outermost(self.body_span),
-                kind: TerminatorKind::Terminate,
+                kind: TerminatorKind::UnwindTerminate,
             }),
             is_cleanup: true,
         });
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 27e39137092..773056e8a17 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -555,13 +555,8 @@ fn write_scope_tree(
         }
 
         let indented_debug_info = format!(
-            "{0:1$}debug {2} => {3:&<4$}{5:?};",
-            INDENT,
-            indent,
-            var_debug_info.name,
-            "",
-            var_debug_info.references as usize,
-            var_debug_info.value,
+            "{0:1$}debug {2} => {3:?};",
+            INDENT, indent, var_debug_info.name, var_debug_info.value,
         );
 
         if tcx.sess.opts.unstable_opts.mir_include_spans {
diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs
index 20a9e6889e4..a5358687c14 100644
--- a/compiler/rustc_middle/src/mir/spanview.rs
+++ b/compiler/rustc_middle/src/mir/spanview.rs
@@ -238,45 +238,6 @@ pub fn source_range_no_file(tcx: TyCtxt<'_>, span: Span) -> String {
     format!("{}:{}-{}:{}", start.line, start.col.to_usize() + 1, end.line, end.col.to_usize() + 1)
 }
 
-pub fn statement_kind_name(statement: &Statement<'_>) -> &'static str {
-    use StatementKind::*;
-    match statement.kind {
-        Assign(..) => "Assign",
-        FakeRead(..) => "FakeRead",
-        SetDiscriminant { .. } => "SetDiscriminant",
-        Deinit(..) => "Deinit",
-        StorageLive(..) => "StorageLive",
-        StorageDead(..) => "StorageDead",
-        Retag(..) => "Retag",
-        PlaceMention(..) => "PlaceMention",
-        AscribeUserType(..) => "AscribeUserType",
-        Coverage(..) => "Coverage",
-        Intrinsic(..) => "Intrinsic",
-        ConstEvalCounter => "ConstEvalCounter",
-        Nop => "Nop",
-    }
-}
-
-pub fn terminator_kind_name(term: &Terminator<'_>) -> &'static str {
-    use TerminatorKind::*;
-    match term.kind {
-        Goto { .. } => "Goto",
-        SwitchInt { .. } => "SwitchInt",
-        Resume => "Resume",
-        Terminate => "Terminate",
-        Return => "Return",
-        Unreachable => "Unreachable",
-        Drop { .. } => "Drop",
-        Call { .. } => "Call",
-        Assert { .. } => "Assert",
-        Yield { .. } => "Yield",
-        GeneratorDrop => "GeneratorDrop",
-        FalseEdge { .. } => "FalseEdge",
-        FalseUnwind { .. } => "FalseUnwind",
-        InlineAsm { .. } => "InlineAsm",
-    }
-}
-
 fn statement_span_viewable<'tcx>(
     tcx: TyCtxt<'tcx>,
     body_span: Span,
@@ -304,7 +265,7 @@ fn terminator_span_viewable<'tcx>(
     if !body_span.contains(span) {
         return None;
     }
-    let id = format!("{}:{}", bb.index(), terminator_kind_name(term));
+    let id = format!("{}:{}", bb.index(), term.kind.name());
     let tooltip = tooltip(tcx, &id, span, vec![], &data.terminator);
     Some(SpanViewable { bb, span, id, tooltip })
 }
@@ -631,7 +592,7 @@ fn tooltip<'tcx>(
             "\n{}{}: {}: {:?}",
             TOOLTIP_INDENT,
             source_range,
-            statement_kind_name(&statement),
+            statement.kind.name(),
             statement
         ));
     }
@@ -641,7 +602,7 @@ fn tooltip<'tcx>(
             "\n{}{}: {}: {:?}",
             TOOLTIP_INDENT,
             source_range,
-            terminator_kind_name(term),
+            term.kind.name(),
             term.kind
         ));
     }
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index be27bf75dbd..e91e822f915 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -380,6 +380,28 @@ pub enum StatementKind<'tcx> {
     Nop,
 }
 
+impl StatementKind<'_> {
+    /// Returns a simple string representation of a `StatementKind` variant, independent of any
+    /// values it might hold (e.g. `StatementKind::Assign` always returns `"Assign"`).
+    pub const fn name(&self) -> &'static str {
+        match self {
+            StatementKind::Assign(..) => "Assign",
+            StatementKind::FakeRead(..) => "FakeRead",
+            StatementKind::SetDiscriminant { .. } => "SetDiscriminant",
+            StatementKind::Deinit(..) => "Deinit",
+            StatementKind::StorageLive(..) => "StorageLive",
+            StatementKind::StorageDead(..) => "StorageDead",
+            StatementKind::Retag(..) => "Retag",
+            StatementKind::PlaceMention(..) => "PlaceMention",
+            StatementKind::AscribeUserType(..) => "AscribeUserType",
+            StatementKind::Coverage(..) => "Coverage",
+            StatementKind::Intrinsic(..) => "Intrinsic",
+            StatementKind::ConstEvalCounter => "ConstEvalCounter",
+            StatementKind::Nop => "Nop",
+        }
+    }
+}
+
 #[derive(
     Clone,
     TyEncodable,
@@ -593,13 +615,13 @@ pub enum TerminatorKind<'tcx> {
     ///
     /// Only permitted in cleanup blocks. `Resume` is not permitted with `-C unwind=abort` after
     /// deaggregation runs.
-    Resume,
+    UnwindResume,
 
     /// 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.
-    Terminate,
+    UnwindTerminate,
 
     /// Returns from the function.
     ///
@@ -790,8 +812,8 @@ impl TerminatorKind<'_> {
         match self {
             TerminatorKind::Goto { .. } => "Goto",
             TerminatorKind::SwitchInt { .. } => "SwitchInt",
-            TerminatorKind::Resume => "Resume",
-            TerminatorKind::Terminate => "Terminate",
+            TerminatorKind::UnwindResume => "UnwindResume",
+            TerminatorKind::UnwindTerminate => "UnwindTerminate",
             TerminatorKind::Return => "Return",
             TerminatorKind::Unreachable => "Unreachable",
             TerminatorKind::Drop { .. } => "Drop",
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 6de84351595..bd87563e2bb 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -10,6 +10,7 @@ use std::iter;
 use std::slice;
 
 pub use super::query::*;
+use super::*;
 
 #[derive(Debug, Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)]
 pub struct SwitchTargets {
@@ -154,8 +155,8 @@ impl<'tcx> TerminatorKind<'tcx> {
             | InlineAsm { destination: Some(t), unwind: _, .. } => {
                 Some(t).into_iter().chain((&[]).into_iter().copied())
             }
-            Resume
-            | Terminate
+            UnwindResume
+            | UnwindTerminate
             | GeneratorDrop
             | Return
             | Unreachable
@@ -196,8 +197,8 @@ impl<'tcx> TerminatorKind<'tcx> {
             | InlineAsm { destination: Some(ref mut t), unwind: _, .. } => {
                 Some(t).into_iter().chain(&mut [])
             }
-            Resume
-            | Terminate
+            UnwindResume
+            | UnwindTerminate
             | GeneratorDrop
             | Return
             | Unreachable
@@ -213,8 +214,8 @@ impl<'tcx> TerminatorKind<'tcx> {
     pub fn unwind(&self) -> Option<&UnwindAction> {
         match *self {
             TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::GeneratorDrop
@@ -232,8 +233,8 @@ impl<'tcx> TerminatorKind<'tcx> {
     pub fn unwind_mut(&mut self) -> Option<&mut UnwindAction> {
         match *self {
             TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::GeneratorDrop
@@ -310,8 +311,8 @@ impl<'tcx> TerminatorKind<'tcx> {
             SwitchInt { discr, .. } => write!(fmt, "switchInt({discr:?})"),
             Return => write!(fmt, "return"),
             GeneratorDrop => write!(fmt, "generator_drop"),
-            Resume => write!(fmt, "resume"),
-            Terminate => write!(fmt, "abort"),
+            UnwindResume => write!(fmt, "resume"),
+            UnwindTerminate => write!(fmt, "abort"),
             Yield { value, resume_arg, .. } => write!(fmt, "{resume_arg:?} = yield({value:?})"),
             Unreachable => write!(fmt, "unreachable"),
             Drop { place, .. } => write!(fmt, "drop({place:?})"),
@@ -390,7 +391,7 @@ impl<'tcx> TerminatorKind<'tcx> {
     pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
         use self::TerminatorKind::*;
         match *self {
-            Return | Resume | Terminate | Unreachable | GeneratorDrop => vec![],
+            Return | UnwindResume | UnwindTerminate | Unreachable | GeneratorDrop => vec![],
             Goto { .. } => vec!["".into()],
             SwitchInt { ref targets, .. } => targets
                 .values
@@ -430,3 +431,110 @@ impl<'tcx> TerminatorKind<'tcx> {
         }
     }
 }
+
+#[derive(Copy, Clone, Debug)]
+pub enum TerminatorEdges<'mir, 'tcx> {
+    /// For terminators that have no successor, like `return`.
+    None,
+    /// For terminators that a single successor, like `goto`, and `assert` without cleanup block.
+    Single(BasicBlock),
+    /// For terminators that two successors, `assert` with cleanup block and `falseEdge`.
+    Double(BasicBlock, BasicBlock),
+    /// Special action for `Yield`, `Call` and `InlineAsm` terminators.
+    AssignOnReturn {
+        return_: Option<BasicBlock>,
+        unwind: UnwindAction,
+        place: CallReturnPlaces<'mir, 'tcx>,
+    },
+    /// Special edge for `SwitchInt`.
+    SwitchInt { targets: &'mir SwitchTargets, discr: &'mir Operand<'tcx> },
+}
+
+/// List of places that are written to after a successful (non-unwind) return
+/// from a `Call`, `Yield` or `InlineAsm`.
+#[derive(Copy, Clone, Debug)]
+pub enum CallReturnPlaces<'a, 'tcx> {
+    Call(Place<'tcx>),
+    Yield(Place<'tcx>),
+    InlineAsm(&'a [InlineAsmOperand<'tcx>]),
+}
+
+impl<'tcx> CallReturnPlaces<'_, 'tcx> {
+    pub fn for_each(&self, mut f: impl FnMut(Place<'tcx>)) {
+        match *self {
+            Self::Call(place) | Self::Yield(place) => f(place),
+            Self::InlineAsm(operands) => {
+                for op in operands {
+                    match *op {
+                        InlineAsmOperand::Out { place: Some(place), .. }
+                        | InlineAsmOperand::InOut { out_place: Some(place), .. } => f(place),
+                        _ => {}
+                    }
+                }
+            }
+        }
+    }
+}
+
+impl<'tcx> Terminator<'tcx> {
+    pub fn edges(&self) -> TerminatorEdges<'_, 'tcx> {
+        self.kind.edges()
+    }
+}
+
+impl<'tcx> TerminatorKind<'tcx> {
+    pub fn edges(&self) -> TerminatorEdges<'_, 'tcx> {
+        use TerminatorKind::*;
+        match *self {
+            Return | UnwindResume | UnwindTerminate | GeneratorDrop | Unreachable => {
+                TerminatorEdges::None
+            }
+
+            Goto { target } => TerminatorEdges::Single(target),
+
+            Assert { target, unwind, expected: _, msg: _, cond: _ }
+            | Drop { target, unwind, place: _, replace: _ }
+            | FalseUnwind { real_target: target, unwind } => match unwind {
+                UnwindAction::Cleanup(unwind) => TerminatorEdges::Double(target, unwind),
+                UnwindAction::Continue | UnwindAction::Terminate | UnwindAction::Unreachable => {
+                    TerminatorEdges::Single(target)
+                }
+            },
+
+            FalseEdge { real_target, imaginary_target } => {
+                TerminatorEdges::Double(real_target, imaginary_target)
+            }
+
+            Yield { resume: target, drop, resume_arg, value: _ } => {
+                TerminatorEdges::AssignOnReturn {
+                    return_: Some(target),
+                    unwind: drop.map_or(UnwindAction::Terminate, UnwindAction::Cleanup),
+                    place: CallReturnPlaces::Yield(resume_arg),
+                }
+            }
+
+            Call { unwind, destination, target, func: _, args: _, fn_span: _, call_source: _ } => {
+                TerminatorEdges::AssignOnReturn {
+                    return_: target,
+                    unwind,
+                    place: CallReturnPlaces::Call(destination),
+                }
+            }
+
+            InlineAsm {
+                template: _,
+                ref operands,
+                options: _,
+                line_spans: _,
+                destination,
+                unwind,
+            } => TerminatorEdges::AssignOnReturn {
+                return_: destination,
+                unwind,
+                place: CallReturnPlaces::InlineAsm(operands),
+            },
+
+            SwitchInt { ref targets, ref discr } => TerminatorEdges::SwitchInt { targets, discr },
+        }
+    }
+}
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 64bc4fa7926..b3d3366ae10 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -469,8 +469,8 @@ macro_rules! make_mir_visitor {
                 self.visit_source_info(source_info);
                 match kind {
                     TerminatorKind::Goto { .. } |
-                    TerminatorKind::Resume |
-                    TerminatorKind::Terminate |
+                    TerminatorKind::UnwindResume |
+                    TerminatorKind::UnwindTerminate |
                     TerminatorKind::GeneratorDrop |
                     TerminatorKind::Unreachable |
                     TerminatorKind::FalseEdge { .. } |
@@ -840,7 +840,6 @@ macro_rules! make_mir_visitor {
                     source_info,
                     value,
                     argument_index: _,
-                    references: _,
                 } = var_debug_info;
 
                 self.visit_source_info(source_info);
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index e289ddab120..94ae0dcb517 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -388,7 +388,6 @@ rustc_queries! {
     }
 
     query shallow_lint_levels_on(key: hir::OwnerId) -> &'tcx rustc_middle::lint::ShallowLintLevelMap {
-        eval_always // fetches `resolutions`
         arena_cache
         desc { |tcx| "looking up lint levels for `{}`", tcx.def_path_str(key) }
     }
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index e71482326da..5db9b775a0f 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -1,6 +1,7 @@
 //! Diagnostics related methods for `Ty`.
 
 use std::borrow::Cow;
+use std::fmt::Write;
 use std::ops::ControlFlow;
 
 use crate::ty::{
@@ -335,10 +336,10 @@ pub fn suggest_constraining_type_params<'a>(
             //                                           - insert: `, X: Bar`
             suggestions.push((
                 generics.tail_span_for_predicate_suggestion(),
-                constraints
-                    .iter()
-                    .map(|&(constraint, _)| format!(", {param_name}: {constraint}"))
-                    .collect::<String>(),
+                constraints.iter().fold(String::new(), |mut string, &(constraint, _)| {
+                    write!(string, ", {param_name}: {constraint}").unwrap();
+                    string
+                }),
                 SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name },
             ));
             continue;
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 1347b35556d..f979ddd00fa 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -438,7 +438,6 @@ CloneLiftImpls! {
     (),
     bool,
     usize,
-    u8,
     u16,
     u32,
     u64,
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index e6baa624205..0291cdd6c57 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -2827,11 +2827,11 @@ impl<'tcx> Ty<'tcx> {
 
             ty::Adt(def, _args) => def.sized_constraint(tcx).skip_binder().is_empty(),
 
-            ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) => false,
+            ty::Alias(..) | ty::Param(_) | ty::Placeholder(..) | ty::Bound(..) => false,
 
             ty::Infer(ty::TyVar(_)) => false,
 
-            ty::Bound(..) | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
+            ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
                 bug!("`is_trivially_sized` applied to unexpected type: {:?}", self)
             }
         }
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 fe5190900e9..26662f5de45 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -61,9 +61,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
                 })
             },
             @call("mir_call", args) => {
-                let destination = self.parse_place(args[0])?;
-                let target = self.parse_block(args[1])?;
-                self.parse_call(args[2], destination, target)
+                self.parse_call(args)
             },
             ExprKind::Match { scrutinee, arms, .. } => {
                 let discr = self.parse_operand(*scrutinee)?;
@@ -109,13 +107,14 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
         Ok(SwitchTargets::new(values.into_iter().zip(targets), otherwise))
     }
 
-    fn parse_call(
-        &self,
-        expr_id: ExprId,
-        destination: Place<'tcx>,
-        target: BasicBlock,
-    ) -> PResult<TerminatorKind<'tcx>> {
-        parse_by_kind!(self, expr_id, _, "function call",
+    fn parse_call(&self, args: &[ExprId]) -> PResult<TerminatorKind<'tcx>> {
+        let (destination, call) = parse_by_kind!(self, args[0], _, "function call",
+            ExprKind::Assign { lhs, rhs } => (*lhs, *rhs),
+        );
+        let destination = self.parse_place(destination)?;
+        let target = self.parse_block(args[1])?;
+
+        parse_by_kind!(self, call, _, "function call",
             ExprKind::Call { fun, args, from_hir_call, fn_span, .. } => {
                 let fun = self.parse_operand(*fun)?;
                 let args = args
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index ed3ac7cb3ec..3c450740712 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -2242,7 +2242,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         self.var_debug_info.push(VarDebugInfo {
             name,
             source_info: debug_source_info,
-            references: 0,
             value: VarDebugInfoContents::Place(for_arm_body.into()),
             argument_index: None,
         });
@@ -2262,7 +2261,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             self.var_debug_info.push(VarDebugInfo {
                 name,
                 source_info: debug_source_info,
-                references: 0,
                 value: VarDebugInfoContents::Place(ref_for_guard.into()),
                 argument_index: None,
             });
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index c66eba5520e..2a23a69b584 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -820,7 +820,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 };
                 self.var_debug_info.push(VarDebugInfo {
                     name,
-                    references: 0,
                     source_info: SourceInfo::outermost(captured_place.var_ident.span),
                     value: VarDebugInfoContents::Place(use_place),
                     argument_index: None,
@@ -851,7 +850,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 self.var_debug_info.push(VarDebugInfo {
                     name,
                     source_info,
-                    references: 0,
                     value: VarDebugInfoContents::Place(arg_local.into()),
                     argument_index: Some(argument_index as u16 + 1),
                 });
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index a96288a11e5..567e7bfb5bf 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -685,9 +685,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         drops.add_entry(block, drop_idx);
 
         // `build_drop_trees` doesn't have access to our source_info, so we
-        // create a dummy terminator now. `TerminatorKind::Resume` is used
+        // create a dummy terminator now. `TerminatorKind::UnwindResume` is used
         // because MIR type checking will panic if it hasn't been overwritten.
-        self.cfg.terminate(block, source_info, TerminatorKind::Resume);
+        self.cfg.terminate(block, source_info, TerminatorKind::UnwindResume);
 
         self.cfg.start_new_block().unit()
     }
@@ -717,9 +717,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         drops.add_entry(block, drop_idx);
 
         // `build_drop_trees` doesn't have access to our source_info, so we
-        // create a dummy terminator now. `TerminatorKind::Resume` is used
+        // create a dummy terminator now. `TerminatorKind::UnwindResume` is used
         // because MIR type checking will panic if it hasn't been overwritten.
-        self.cfg.terminate(block, source_info, TerminatorKind::Resume);
+        self.cfg.terminate(block, source_info, TerminatorKind::UnwindResume);
     }
 
     // Add a dummy `Assign` statement to the CFG, with the span for the source code's `continue`
@@ -1441,7 +1441,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
         blocks[ROOT_NODE] = *resume_block;
         drops.build_mir::<Unwind>(cfg, &mut blocks);
         if let (None, Some(resume)) = (*resume_block, blocks[ROOT_NODE]) {
-            cfg.terminate(resume, SourceInfo::outermost(fn_span), TerminatorKind::Resume);
+            cfg.terminate(resume, SourceInfo::outermost(fn_span), TerminatorKind::UnwindResume);
 
             *resume_block = blocks[ROOT_NODE];
         }
@@ -1506,8 +1506,8 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind {
             }
             TerminatorKind::Goto { .. }
             | TerminatorKind::SwitchInt { .. }
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | 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 7fb73b5c7b2..84c80bf41a4 100644
--- a/compiler/rustc_mir_build/src/lints.rs
+++ b/compiler/rustc_mir_build/src/lints.rs
@@ -186,9 +186,9 @@ impl<'mir, 'tcx, C: TerminatorClassifier<'tcx>> TriColorVisitor<BasicBlocks<'tcx
 
         match self.body[bb].terminator().kind {
             // These terminators return control flow to the caller.
-            TerminatorKind::Terminate
+            TerminatorKind::UnwindTerminate
             | TerminatorKind::GeneratorDrop
-            | TerminatorKind::Resume
+            | TerminatorKind::UnwindResume
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::Yield { .. } => ControlFlow::Break(NonRecursive),
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index 804b44a6bf0..8a9e37c5a4f 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -1,11 +1,10 @@
-use rustc_middle::mir::{self, BasicBlock, Location, SwitchTargets, UnwindAction};
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::mir::{
+    self, BasicBlock, CallReturnPlaces, Location, SwitchTargets, TerminatorEdges, UnwindAction,
+};
 use std::ops::RangeInclusive;
 
 use super::visitor::{ResultsVisitable, ResultsVisitor};
-use super::{
-    Analysis, CallReturnPlaces, Effect, EffectIndex, GenKillAnalysis, GenKillSet, SwitchIntTarget,
-};
+use super::{Analysis, Effect, EffectIndex, GenKillAnalysis, GenKillSet, SwitchIntTarget};
 
 pub trait Direction {
     const IS_FORWARD: bool;
@@ -24,15 +23,17 @@ pub trait Direction {
     ) where
         A: Analysis<'tcx>;
 
-    fn apply_effects_in_block<'tcx, A>(
+    fn apply_effects_in_block<'mir, 'tcx, A>(
         analysis: &mut A,
         state: &mut A::Domain,
         block: BasicBlock,
-        block_data: &mir::BasicBlockData<'tcx>,
-    ) where
+        block_data: &'mir mir::BasicBlockData<'tcx>,
+        statement_effect: Option<&dyn Fn(BasicBlock, &mut A::Domain)>,
+    ) -> TerminatorEdges<'mir, 'tcx>
+    where
         A: Analysis<'tcx>;
 
-    fn gen_kill_effects_in_block<'tcx, A>(
+    fn gen_kill_statement_effects_in_block<'tcx, A>(
         analysis: &mut A,
         trans: &mut GenKillSet<A::Idx>,
         block: BasicBlock,
@@ -51,10 +52,10 @@ pub trait Direction {
 
     fn join_state_into_successors_of<'tcx, A>(
         analysis: &mut A,
-        tcx: TyCtxt<'tcx>,
         body: &mir::Body<'tcx>,
         exit_state: &mut A::Domain,
-        block: (BasicBlock, &'_ mir::BasicBlockData<'tcx>),
+        block: BasicBlock,
+        edges: TerminatorEdges<'_, 'tcx>,
         propagate: impl FnMut(BasicBlock, &A::Domain),
     ) where
         A: Analysis<'tcx>;
@@ -66,27 +67,33 @@ pub struct Backward;
 impl Direction for Backward {
     const IS_FORWARD: bool = false;
 
-    fn apply_effects_in_block<'tcx, A>(
+    fn apply_effects_in_block<'mir, 'tcx, A>(
         analysis: &mut A,
         state: &mut A::Domain,
         block: BasicBlock,
-        block_data: &mir::BasicBlockData<'tcx>,
-    ) where
+        block_data: &'mir mir::BasicBlockData<'tcx>,
+        statement_effect: Option<&dyn Fn(BasicBlock, &mut A::Domain)>,
+    ) -> TerminatorEdges<'mir, 'tcx>
+    where
         A: Analysis<'tcx>,
     {
         let terminator = block_data.terminator();
         let location = Location { block, statement_index: block_data.statements.len() };
         analysis.apply_before_terminator_effect(state, terminator, location);
-        analysis.apply_terminator_effect(state, terminator, location);
-
-        for (statement_index, statement) in block_data.statements.iter().enumerate().rev() {
-            let location = Location { block, statement_index };
-            analysis.apply_before_statement_effect(state, statement, location);
-            analysis.apply_statement_effect(state, statement, location);
+        let edges = analysis.apply_terminator_effect(state, terminator, location);
+        if let Some(statement_effect) = statement_effect {
+            statement_effect(block, state)
+        } else {
+            for (statement_index, statement) in block_data.statements.iter().enumerate().rev() {
+                let location = Location { block, statement_index };
+                analysis.apply_before_statement_effect(state, statement, location);
+                analysis.apply_statement_effect(state, statement, location);
+            }
         }
+        edges
     }
 
-    fn gen_kill_effects_in_block<'tcx, A>(
+    fn gen_kill_statement_effects_in_block<'tcx, A>(
         analysis: &mut A,
         trans: &mut GenKillSet<A::Idx>,
         block: BasicBlock,
@@ -94,11 +101,6 @@ impl Direction for Backward {
     ) where
         A: GenKillAnalysis<'tcx>,
     {
-        let terminator = block_data.terminator();
-        let location = Location { block, statement_index: block_data.statements.len() };
-        analysis.before_terminator_effect(trans, terminator, location);
-        analysis.terminator_effect(trans, terminator, location);
-
         for (statement_index, statement) in block_data.statements.iter().enumerate().rev() {
             let location = Location { block, statement_index };
             analysis.before_statement_effect(trans, statement, location);
@@ -217,10 +219,10 @@ impl Direction for Backward {
 
     fn join_state_into_successors_of<'tcx, A>(
         analysis: &mut A,
-        _tcx: TyCtxt<'tcx>,
         body: &mir::Body<'tcx>,
         exit_state: &mut A::Domain,
-        (bb, _bb_data): (BasicBlock, &'_ mir::BasicBlockData<'tcx>),
+        bb: BasicBlock,
+        _edges: TerminatorEdges<'_, 'tcx>,
         mut propagate: impl FnMut(BasicBlock, &A::Domain),
     ) where
         A: Analysis<'tcx>,
@@ -254,7 +256,11 @@ impl Direction for Backward {
 
                 mir::TerminatorKind::Yield { resume, resume_arg, .. } if resume == bb => {
                     let mut tmp = exit_state.clone();
-                    analysis.apply_yield_resume_effect(&mut tmp, resume, resume_arg);
+                    analysis.apply_call_return_effect(
+                        &mut tmp,
+                        resume,
+                        CallReturnPlaces::Yield(resume_arg),
+                    );
                     propagate(pred, &tmp);
                 }
 
@@ -318,27 +324,33 @@ pub struct Forward;
 impl Direction for Forward {
     const IS_FORWARD: bool = true;
 
-    fn apply_effects_in_block<'tcx, A>(
+    fn apply_effects_in_block<'mir, 'tcx, A>(
         analysis: &mut A,
         state: &mut A::Domain,
         block: BasicBlock,
-        block_data: &mir::BasicBlockData<'tcx>,
-    ) where
+        block_data: &'mir mir::BasicBlockData<'tcx>,
+        statement_effect: Option<&dyn Fn(BasicBlock, &mut A::Domain)>,
+    ) -> TerminatorEdges<'mir, 'tcx>
+    where
         A: Analysis<'tcx>,
     {
-        for (statement_index, statement) in block_data.statements.iter().enumerate() {
-            let location = Location { block, statement_index };
-            analysis.apply_before_statement_effect(state, statement, location);
-            analysis.apply_statement_effect(state, statement, location);
+        if let Some(statement_effect) = statement_effect {
+            statement_effect(block, state)
+        } else {
+            for (statement_index, statement) in block_data.statements.iter().enumerate() {
+                let location = Location { block, statement_index };
+                analysis.apply_before_statement_effect(state, statement, location);
+                analysis.apply_statement_effect(state, statement, location);
+            }
         }
 
         let terminator = block_data.terminator();
         let location = Location { block, statement_index: block_data.statements.len() };
         analysis.apply_before_terminator_effect(state, terminator, location);
-        analysis.apply_terminator_effect(state, terminator, location);
+        analysis.apply_terminator_effect(state, terminator, location)
     }
 
-    fn gen_kill_effects_in_block<'tcx, A>(
+    fn gen_kill_statement_effects_in_block<'tcx, A>(
         analysis: &mut A,
         trans: &mut GenKillSet<A::Idx>,
         block: BasicBlock,
@@ -351,11 +363,6 @@ impl Direction for Forward {
             analysis.before_statement_effect(trans, statement, location);
             analysis.statement_effect(trans, statement, location);
         }
-
-        let terminator = block_data.terminator();
-        let location = Location { block, statement_index: block_data.statements.len() };
-        analysis.before_terminator_effect(trans, terminator, location);
-        analysis.terminator_effect(trans, terminator, location);
     }
 
     fn apply_effects_in_range<'tcx, A>(
@@ -464,86 +471,32 @@ impl Direction for Forward {
 
     fn join_state_into_successors_of<'tcx, A>(
         analysis: &mut A,
-        _tcx: TyCtxt<'tcx>,
         _body: &mir::Body<'tcx>,
         exit_state: &mut A::Domain,
-        (bb, bb_data): (BasicBlock, &'_ mir::BasicBlockData<'tcx>),
+        bb: BasicBlock,
+        edges: TerminatorEdges<'_, 'tcx>,
         mut propagate: impl FnMut(BasicBlock, &A::Domain),
     ) where
         A: Analysis<'tcx>,
     {
-        use mir::TerminatorKind::*;
-        match bb_data.terminator().kind {
-            Return | Resume | Terminate | GeneratorDrop | Unreachable => {}
-
-            Goto { target } => propagate(target, exit_state),
-
-            Assert { target, unwind, expected: _, msg: _, cond: _ }
-            | Drop { target, unwind, place: _, replace: _ }
-            | FalseUnwind { real_target: target, unwind } => {
-                if let UnwindAction::Cleanup(unwind) = unwind {
-                    propagate(unwind, exit_state);
-                }
-
+        match edges {
+            TerminatorEdges::None => {}
+            TerminatorEdges::Single(target) => propagate(target, exit_state),
+            TerminatorEdges::Double(target, unwind) => {
                 propagate(target, exit_state);
+                propagate(unwind, exit_state);
             }
-
-            FalseEdge { real_target, imaginary_target } => {
-                propagate(real_target, exit_state);
-                propagate(imaginary_target, exit_state);
-            }
-
-            Yield { resume: target, drop, resume_arg, value: _ } => {
-                if let Some(drop) = drop {
-                    propagate(drop, exit_state);
-                }
-
-                analysis.apply_yield_resume_effect(exit_state, target, resume_arg);
-                propagate(target, exit_state);
-            }
-
-            Call { unwind, destination, target, func: _, args: _, call_source: _, fn_span: _ } => {
-                if let UnwindAction::Cleanup(unwind) = unwind {
-                    propagate(unwind, exit_state);
-                }
-
-                if let Some(target) = target {
-                    // N.B.: This must be done *last*, otherwise the unwind path will see the call
-                    // return effect.
-                    analysis.apply_call_return_effect(
-                        exit_state,
-                        bb,
-                        CallReturnPlaces::Call(destination),
-                    );
-                    propagate(target, exit_state);
-                }
-            }
-
-            InlineAsm {
-                template: _,
-                ref operands,
-                options: _,
-                line_spans: _,
-                destination,
-                unwind,
-            } => {
+            TerminatorEdges::AssignOnReturn { return_, unwind, place } => {
+                // This must be done *first*, otherwise the unwind path will see the assignments.
                 if let UnwindAction::Cleanup(unwind) = unwind {
                     propagate(unwind, exit_state);
                 }
-
-                if let Some(target) = destination {
-                    // N.B.: This must be done *last*, otherwise the unwind path will see the call
-                    // return effect.
-                    analysis.apply_call_return_effect(
-                        exit_state,
-                        bb,
-                        CallReturnPlaces::InlineAsm(operands),
-                    );
-                    propagate(target, exit_state);
+                if let Some(return_) = return_ {
+                    analysis.apply_call_return_effect(exit_state, bb, place);
+                    propagate(return_, exit_state);
                 }
             }
-
-            SwitchInt { ref targets, ref discr } => {
+            TerminatorEdges::SwitchInt { targets, discr } => {
                 let mut applier = ForwardSwitchIntEdgeEffectsApplier {
                     exit_state,
                     targets,
diff --git a/compiler/rustc_mir_dataflow/src/framework/engine.rs b/compiler/rustc_mir_dataflow/src/framework/engine.rs
index c755d7588c2..a29962d7717 100644
--- a/compiler/rustc_mir_dataflow/src/framework/engine.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/engine.rs
@@ -144,7 +144,7 @@ where
     // gen/kill problems on cyclic CFGs. This is not ideal, but it doesn't seem to degrade
     // performance in practice. I've tried a few ways to avoid this, but they have downsides. See
     // the message for the commit that added this FIXME for more information.
-    apply_trans_for_block: Option<Box<dyn Fn(BasicBlock, &mut A::Domain)>>,
+    apply_statement_trans_for_block: Option<Box<dyn Fn(BasicBlock, &mut A::Domain)>>,
 }
 
 impl<'a, 'tcx, A, D, T> Engine<'a, 'tcx, A>
@@ -165,12 +165,17 @@ where
 
         // Otherwise, compute and store the cumulative transfer function for each block.
 
-        let identity = GenKillSet::identity(analysis.bottom_value(body).domain_size());
+        let identity = GenKillSet::identity(analysis.domain_size(body));
         let mut trans_for_block = IndexVec::from_elem(identity, &body.basic_blocks);
 
         for (block, block_data) in body.basic_blocks.iter_enumerated() {
             let trans = &mut trans_for_block[block];
-            A::Direction::gen_kill_effects_in_block(&mut analysis, trans, block, block_data);
+            A::Direction::gen_kill_statement_effects_in_block(
+                &mut analysis,
+                trans,
+                block,
+                block_data,
+            );
         }
 
         let apply_trans = Box::new(move |bb: BasicBlock, state: &mut A::Domain| {
@@ -199,17 +204,18 @@ where
         tcx: TyCtxt<'tcx>,
         body: &'a mir::Body<'tcx>,
         analysis: A,
-        apply_trans_for_block: Option<Box<dyn Fn(BasicBlock, &mut A::Domain)>>,
+        apply_statement_trans_for_block: Option<Box<dyn Fn(BasicBlock, &mut A::Domain)>>,
     ) -> Self {
-        let bottom_value = analysis.bottom_value(body);
-        let mut entry_sets = IndexVec::from_elem(bottom_value.clone(), &body.basic_blocks);
+        let mut entry_sets =
+            IndexVec::from_fn_n(|_| analysis.bottom_value(body), body.basic_blocks.len());
         analysis.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]);
 
-        if A::Direction::IS_BACKWARD && entry_sets[mir::START_BLOCK] != bottom_value {
+        if A::Direction::IS_BACKWARD && entry_sets[mir::START_BLOCK] != analysis.bottom_value(body)
+        {
             bug!("`initialize_start_block` is not yet supported for backward dataflow analyses");
         }
 
-        Engine { analysis, tcx, body, pass_name: None, entry_sets, apply_trans_for_block }
+        Engine { analysis, tcx, body, pass_name: None, entry_sets, apply_statement_trans_for_block }
     }
 
     /// Adds an identifier to the graphviz output for this particular run of a dataflow analysis.
@@ -231,7 +237,7 @@ where
             body,
             mut entry_sets,
             tcx,
-            apply_trans_for_block,
+            apply_statement_trans_for_block,
             pass_name,
             ..
         } = self;
@@ -263,19 +269,20 @@ where
             state.clone_from(&entry_sets[bb]);
 
             // Apply the block transfer function, using the cached one if it exists.
-            match &apply_trans_for_block {
-                Some(apply) => apply(bb, &mut state),
-                None => {
-                    A::Direction::apply_effects_in_block(&mut analysis, &mut state, bb, bb_data)
-                }
-            }
+            let edges = A::Direction::apply_effects_in_block(
+                &mut analysis,
+                &mut state,
+                bb,
+                bb_data,
+                apply_statement_trans_for_block.as_deref(),
+            );
 
             A::Direction::join_state_into_successors_of(
                 &mut analysis,
-                tcx,
                 body,
                 &mut state,
-                (bb, bb_data),
+                bb,
+                edges,
                 |target: BasicBlock, state: &A::Domain| {
                     let set_changed = entry_sets[target].join(state);
                     if set_changed {
diff --git a/compiler/rustc_mir_dataflow/src/framework/fmt.rs b/compiler/rustc_mir_dataflow/src/framework/fmt.rs
index 6a256fae3ca..e3a66bd952c 100644
--- a/compiler/rustc_mir_dataflow/src/framework/fmt.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/fmt.rs
@@ -1,6 +1,7 @@
 //! Custom formatting traits used when outputting Graphviz diagrams with the results of a dataflow
 //! analysis.
 
+use super::lattice::MaybeReachable;
 use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet};
 use rustc_index::Idx;
 use std::fmt;
@@ -124,6 +125,37 @@ where
     }
 }
 
+impl<S, C> DebugWithContext<C> for MaybeReachable<S>
+where
+    S: DebugWithContext<C>,
+{
+    fn fmt_with(&self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            MaybeReachable::Unreachable => {
+                write!(f, "unreachable")
+            }
+            MaybeReachable::Reachable(set) => set.fmt_with(ctxt, f),
+        }
+    }
+
+    fn fmt_diff_with(&self, old: &Self, ctxt: &C, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match (self, old) {
+            (MaybeReachable::Unreachable, MaybeReachable::Unreachable) => Ok(()),
+            (MaybeReachable::Unreachable, MaybeReachable::Reachable(set)) => {
+                write!(f, "\u{001f}+")?;
+                set.fmt_with(ctxt, f)
+            }
+            (MaybeReachable::Reachable(set), MaybeReachable::Unreachable) => {
+                write!(f, "\u{001f}-")?;
+                set.fmt_with(ctxt, f)
+            }
+            (MaybeReachable::Reachable(this), MaybeReachable::Reachable(old)) => {
+                this.fmt_diff_with(old, ctxt, f)
+            }
+        }
+    }
+}
+
 fn fmt_diff<T, C>(
     inserted: &HybridBitSet<T>,
     removed: &HybridBitSet<T>,
diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
index e331533c371..1421d9b45cd 100644
--- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs
@@ -269,7 +269,11 @@ where
                 self.write_row(w, "", "(on yield resume)", |this, w, fmt| {
                     let state_on_generator_drop = this.results.get().clone();
                     this.results.apply_custom_effect(|analysis, state| {
-                        analysis.apply_yield_resume_effect(state, resume, resume_arg);
+                        analysis.apply_call_return_effect(
+                            state,
+                            resume,
+                            CallReturnPlaces::Yield(resume_arg),
+                        );
                     });
 
                     write!(
diff --git a/compiler/rustc_mir_dataflow/src/framework/lattice.rs b/compiler/rustc_mir_dataflow/src/framework/lattice.rs
index 3952f44ad48..3b89598d289 100644
--- a/compiler/rustc_mir_dataflow/src/framework/lattice.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/lattice.rs
@@ -187,10 +187,6 @@ impl<T: Idx> MeetSemiLattice for ChunkedBitSet<T> {
 pub struct Dual<T>(pub T);
 
 impl<T: Idx> BitSetExt<T> for Dual<BitSet<T>> {
-    fn domain_size(&self) -> usize {
-        self.0.domain_size()
-    }
-
     fn contains(&self, elem: T) -> bool {
         self.0.contains(elem)
     }
@@ -276,3 +272,93 @@ impl<T> HasBottom for FlatSet<T> {
 impl<T> HasTop for FlatSet<T> {
     const TOP: Self = Self::Top;
 }
+
+/// Extend a lattice with a bottom value to represent an unreachable execution.
+///
+/// The only useful action on an unreachable state is joining it with a reachable one to make it
+/// reachable. All other actions, gen/kill for instance, are no-ops.
+#[derive(PartialEq, Eq, Debug)]
+pub enum MaybeReachable<T> {
+    Unreachable,
+    Reachable(T),
+}
+
+impl<T> MaybeReachable<T> {
+    pub fn is_reachable(&self) -> bool {
+        matches!(self, MaybeReachable::Reachable(_))
+    }
+}
+
+impl<T> HasBottom for MaybeReachable<T> {
+    const BOTTOM: Self = MaybeReachable::Unreachable;
+}
+
+impl<T: HasTop> HasTop for MaybeReachable<T> {
+    const TOP: Self = MaybeReachable::Reachable(T::TOP);
+}
+
+impl<S> MaybeReachable<S> {
+    /// Return whether the current state contains the given element. If the state is unreachable,
+    /// it does no contain anything.
+    pub fn contains<T>(&self, elem: T) -> bool
+    where
+        S: BitSetExt<T>,
+    {
+        match self {
+            MaybeReachable::Unreachable => false,
+            MaybeReachable::Reachable(set) => set.contains(elem),
+        }
+    }
+}
+
+impl<T, S: BitSetExt<T>> BitSetExt<T> for MaybeReachable<S> {
+    fn contains(&self, elem: T) -> bool {
+        self.contains(elem)
+    }
+
+    fn union(&mut self, other: &HybridBitSet<T>) {
+        match self {
+            MaybeReachable::Unreachable => {}
+            MaybeReachable::Reachable(set) => set.union(other),
+        }
+    }
+
+    fn subtract(&mut self, other: &HybridBitSet<T>) {
+        match self {
+            MaybeReachable::Unreachable => {}
+            MaybeReachable::Reachable(set) => set.subtract(other),
+        }
+    }
+}
+
+impl<V: Clone> Clone for MaybeReachable<V> {
+    fn clone(&self) -> Self {
+        match self {
+            MaybeReachable::Reachable(x) => MaybeReachable::Reachable(x.clone()),
+            MaybeReachable::Unreachable => MaybeReachable::Unreachable,
+        }
+    }
+
+    fn clone_from(&mut self, source: &Self) {
+        match (&mut *self, source) {
+            (MaybeReachable::Reachable(x), MaybeReachable::Reachable(y)) => {
+                x.clone_from(&y);
+            }
+            _ => *self = source.clone(),
+        }
+    }
+}
+
+impl<T: JoinSemiLattice + Clone> JoinSemiLattice for MaybeReachable<T> {
+    fn join(&mut self, other: &Self) -> bool {
+        // Unreachable acts as a bottom.
+        match (&mut *self, &other) {
+            (_, MaybeReachable::Unreachable) => false,
+            (MaybeReachable::Unreachable, _) => {
+                *self = other.clone();
+                true
+            }
+            (MaybeReachable::Reachable(this), MaybeReachable::Reachable(other)) => this.join(other),
+        }
+    }
+}
diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs
index 58df9b9a768..ce30c642fcc 100644
--- a/compiler/rustc_mir_dataflow/src/framework/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs
@@ -34,7 +34,7 @@ use std::cmp::Ordering;
 
 use rustc_index::bit_set::{BitSet, ChunkedBitSet, HybridBitSet};
 use rustc_index::Idx;
-use rustc_middle::mir::{self, BasicBlock, Location};
+use rustc_middle::mir::{self, BasicBlock, CallReturnPlaces, Location, TerminatorEdges};
 use rustc_middle::ty::TyCtxt;
 
 mod cursor;
@@ -48,23 +48,18 @@ mod visitor;
 pub use self::cursor::{AnalysisResults, ResultsClonedCursor, ResultsCursor, ResultsRefCursor};
 pub use self::direction::{Backward, Direction, Forward};
 pub use self::engine::{Engine, EntrySets, Results, ResultsCloned};
-pub use self::lattice::{JoinSemiLattice, MeetSemiLattice};
+pub use self::lattice::{JoinSemiLattice, MaybeReachable, MeetSemiLattice};
 pub use self::visitor::{visit_results, ResultsVisitable, ResultsVisitor};
 
 /// Analysis domains are all bitsets of various kinds. This trait holds
 /// operations needed by all of them.
 pub trait BitSetExt<T> {
-    fn domain_size(&self) -> usize;
     fn contains(&self, elem: T) -> bool;
     fn union(&mut self, other: &HybridBitSet<T>);
     fn subtract(&mut self, other: &HybridBitSet<T>);
 }
 
 impl<T: Idx> BitSetExt<T> for BitSet<T> {
-    fn domain_size(&self) -> usize {
-        self.domain_size()
-    }
-
     fn contains(&self, elem: T) -> bool {
         self.contains(elem)
     }
@@ -79,10 +74,6 @@ impl<T: Idx> BitSetExt<T> for BitSet<T> {
 }
 
 impl<T: Idx> BitSetExt<T> for ChunkedBitSet<T> {
-    fn domain_size(&self) -> usize {
-        self.domain_size()
-    }
-
     fn contains(&self, elem: T) -> bool {
         self.contains(elem)
     }
@@ -172,12 +163,12 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
     /// in this function. That should go in `apply_call_return_effect`. For example, in the
     /// `InitializedPlaces` analyses, the return place for a function call is not marked as
     /// initialized here.
-    fn apply_terminator_effect(
+    fn apply_terminator_effect<'mir>(
         &mut self,
         state: &mut Self::Domain,
-        terminator: &mir::Terminator<'tcx>,
+        terminator: &'mir mir::Terminator<'tcx>,
         location: Location,
-    );
+    ) -> TerminatorEdges<'mir, 'tcx>;
 
     /// Updates the current dataflow state with an effect that occurs immediately *before* the
     /// given terminator.
@@ -207,20 +198,6 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
         return_places: CallReturnPlaces<'_, 'tcx>,
     );
 
-    /// Updates the current dataflow state with the effect of resuming from a `Yield` terminator.
-    ///
-    /// This is similar to `apply_call_return_effect` in that it only takes place after the
-    /// generator is resumed, not when it is dropped.
-    ///
-    /// By default, no effects happen.
-    fn apply_yield_resume_effect(
-        &mut self,
-        _state: &mut Self::Domain,
-        _resume_block: BasicBlock,
-        _resume_place: mir::Place<'tcx>,
-    ) {
-    }
-
     /// Updates the current dataflow state with the effect of taking a particular branch in a
     /// `SwitchInt` terminator.
     ///
@@ -295,6 +272,8 @@ where
 pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
     type Idx: Idx;
 
+    fn domain_size(&self, body: &mir::Body<'tcx>) -> usize;
+
     /// See `Analysis::apply_statement_effect`.
     fn statement_effect(
         &mut self,
@@ -313,12 +292,12 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
     }
 
     /// See `Analysis::apply_terminator_effect`.
-    fn terminator_effect(
+    fn terminator_effect<'mir>(
         &mut self,
-        trans: &mut impl GenKill<Self::Idx>,
-        terminator: &mir::Terminator<'tcx>,
+        trans: &mut Self::Domain,
+        terminator: &'mir mir::Terminator<'tcx>,
         location: Location,
-    );
+    ) -> TerminatorEdges<'mir, 'tcx>;
 
     /// See `Analysis::apply_before_terminator_effect`.
     fn before_terminator_effect(
@@ -339,15 +318,6 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> {
         return_places: CallReturnPlaces<'_, 'tcx>,
     );
 
-    /// See `Analysis::apply_yield_resume_effect`.
-    fn yield_resume_effect(
-        &mut self,
-        _trans: &mut impl GenKill<Self::Idx>,
-        _resume_block: BasicBlock,
-        _resume_place: mir::Place<'tcx>,
-    ) {
-    }
-
     /// See `Analysis::apply_switch_int_edge_effects`.
     fn switch_int_edge_effects<G: GenKill<Self::Idx>>(
         &mut self,
@@ -381,13 +351,13 @@ where
         self.before_statement_effect(state, statement, location);
     }
 
-    fn apply_terminator_effect(
+    fn apply_terminator_effect<'mir>(
         &mut self,
         state: &mut A::Domain,
-        terminator: &mir::Terminator<'tcx>,
+        terminator: &'mir mir::Terminator<'tcx>,
         location: Location,
-    ) {
-        self.terminator_effect(state, terminator, location);
+    ) -> TerminatorEdges<'mir, 'tcx> {
+        self.terminator_effect(state, terminator, location)
     }
 
     fn apply_before_terminator_effect(
@@ -410,15 +380,6 @@ where
         self.call_return_effect(state, block, return_places);
     }
 
-    fn apply_yield_resume_effect(
-        &mut self,
-        state: &mut A::Domain,
-        resume_block: BasicBlock,
-        resume_place: mir::Place<'tcx>,
-    ) {
-        self.yield_resume_effect(state, resume_block, resume_place);
-    }
-
     fn apply_switch_int_edge_effects(
         &mut self,
         block: BasicBlock,
@@ -531,6 +492,24 @@ impl<T: Idx> GenKill<T> for ChunkedBitSet<T> {
     }
 }
 
+impl<T, S: GenKill<T>> GenKill<T> for MaybeReachable<S> {
+    fn gen(&mut self, elem: T) {
+        match self {
+            // If the state is not reachable, adding an element does nothing.
+            MaybeReachable::Unreachable => {}
+            MaybeReachable::Reachable(set) => set.gen(elem),
+        }
+    }
+
+    fn kill(&mut self, elem: T) {
+        match self {
+            // If the state is not reachable, killing an element does nothing.
+            MaybeReachable::Unreachable => {}
+            MaybeReachable::Reachable(set) => set.kill(elem),
+        }
+    }
+}
+
 impl<T: Idx> GenKill<T> for lattice::Dual<BitSet<T>> {
     fn gen(&mut self, elem: T) {
         self.0.insert(elem);
@@ -612,29 +591,5 @@ pub trait SwitchIntEdgeEffects<D> {
     fn apply(&mut self, apply_edge_effect: impl FnMut(&mut D, SwitchIntTarget));
 }
 
-/// List of places that are written to after a successful (non-unwind) return
-/// from a `Call` or `InlineAsm`.
-pub enum CallReturnPlaces<'a, 'tcx> {
-    Call(mir::Place<'tcx>),
-    InlineAsm(&'a [mir::InlineAsmOperand<'tcx>]),
-}
-
-impl<'tcx> CallReturnPlaces<'_, 'tcx> {
-    pub fn for_each(&self, mut f: impl FnMut(mir::Place<'tcx>)) {
-        match *self {
-            Self::Call(place) => f(place),
-            Self::InlineAsm(operands) => {
-                for op in operands {
-                    match *op {
-                        mir::InlineAsmOperand::Out { place: Some(place), .. }
-                        | mir::InlineAsmOperand::InOut { out_place: Some(place), .. } => f(place),
-                        _ => {}
-                    }
-                }
-            }
-        }
-    }
-}
-
 #[cfg(test)]
 mod tests;
diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs
index cb0ec144ef0..9cce5b26cd3 100644
--- a/compiler/rustc_mir_dataflow/src/framework/tests.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs
@@ -198,14 +198,15 @@ impl<'tcx, D: Direction> Analysis<'tcx> for MockAnalysis<'tcx, D> {
         assert!(state.insert(idx));
     }
 
-    fn apply_terminator_effect(
+    fn apply_terminator_effect<'mir>(
         &mut self,
         state: &mut Self::Domain,
-        _terminator: &mir::Terminator<'tcx>,
+        terminator: &'mir mir::Terminator<'tcx>,
         location: Location,
-    ) {
+    ) -> TerminatorEdges<'mir, 'tcx> {
         let idx = self.effect(Effect::Primary.at_index(location.statement_index));
         assert!(state.insert(idx));
+        terminator.edges()
     }
 
     fn apply_before_terminator_effect(
diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
index b88ed32b687..5ed8f20b73f 100644
--- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
@@ -1,9 +1,9 @@
-use super::*;
-
-use crate::{AnalysisDomain, CallReturnPlaces, GenKill, GenKillAnalysis};
+use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
 
+use crate::{AnalysisDomain, GenKill, GenKillAnalysis};
+
 /// A dataflow analysis that tracks whether a pointer or reference could possibly exist that points
 /// to a given local.
 ///
@@ -14,7 +14,7 @@ use rustc_middle::mir::*;
 pub struct MaybeBorrowedLocals;
 
 impl MaybeBorrowedLocals {
-    fn transfer_function<'a, T>(&'a self, trans: &'a mut T) -> TransferFunction<'a, T> {
+    pub(super) fn transfer_function<'a, T>(&'a self, trans: &'a mut T) -> TransferFunction<'a, T> {
         TransferFunction { trans }
     }
 }
@@ -23,12 +23,12 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeBorrowedLocals {
     type Domain = BitSet<Local>;
     const NAME: &'static str = "maybe_borrowed_locals";
 
-    fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
+    fn bottom_value(&self, body: &Body<'tcx>) -> Self::Domain {
         // bottom = unborrowed
         BitSet::new_empty(body.local_decls().len())
     }
 
-    fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut Self::Domain) {
+    fn initialize_start_block(&self, _: &Body<'tcx>, _: &mut Self::Domain) {
         // No locals are aliased on function entry
     }
 }
@@ -36,35 +36,40 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeBorrowedLocals {
 impl<'tcx> GenKillAnalysis<'tcx> for MaybeBorrowedLocals {
     type Idx = Local;
 
+    fn domain_size(&self, body: &Body<'tcx>) -> usize {
+        body.local_decls.len()
+    }
+
     fn statement_effect(
         &mut self,
         trans: &mut impl GenKill<Self::Idx>,
-        statement: &mir::Statement<'tcx>,
+        statement: &Statement<'tcx>,
         location: Location,
     ) {
         self.transfer_function(trans).visit_statement(statement, location);
     }
 
-    fn terminator_effect(
+    fn terminator_effect<'mir>(
         &mut self,
-        trans: &mut impl GenKill<Self::Idx>,
-        terminator: &mir::Terminator<'tcx>,
+        trans: &mut Self::Domain,
+        terminator: &'mir Terminator<'tcx>,
         location: Location,
-    ) {
+    ) -> TerminatorEdges<'mir, 'tcx> {
         self.transfer_function(trans).visit_terminator(terminator, location);
+        terminator.edges()
     }
 
     fn call_return_effect(
         &mut self,
         _trans: &mut impl GenKill<Self::Idx>,
-        _block: mir::BasicBlock,
+        _block: BasicBlock,
         _return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
     }
 }
 
 /// A `Visitor` that defines the transfer function for `MaybeBorrowedLocals`.
-struct TransferFunction<'a, T> {
+pub(super) struct TransferFunction<'a, T> {
     trans: &'a mut T,
 }
 
@@ -82,37 +87,37 @@ where
         }
     }
 
-    fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
+    fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
         self.super_rvalue(rvalue, location);
 
         match rvalue {
-            mir::Rvalue::AddressOf(_, borrowed_place) | mir::Rvalue::Ref(_, _, borrowed_place) => {
+            Rvalue::AddressOf(_, borrowed_place) | Rvalue::Ref(_, _, borrowed_place) => {
                 if !borrowed_place.is_indirect() {
                     self.trans.gen(borrowed_place.local);
                 }
             }
 
-            mir::Rvalue::Cast(..)
-            | mir::Rvalue::ShallowInitBox(..)
-            | mir::Rvalue::Use(..)
-            | mir::Rvalue::ThreadLocalRef(..)
-            | mir::Rvalue::Repeat(..)
-            | mir::Rvalue::Len(..)
-            | mir::Rvalue::BinaryOp(..)
-            | mir::Rvalue::CheckedBinaryOp(..)
-            | mir::Rvalue::NullaryOp(..)
-            | mir::Rvalue::UnaryOp(..)
-            | mir::Rvalue::Discriminant(..)
-            | mir::Rvalue::Aggregate(..)
-            | mir::Rvalue::CopyForDeref(..) => {}
+            Rvalue::Cast(..)
+            | Rvalue::ShallowInitBox(..)
+            | Rvalue::Use(..)
+            | Rvalue::ThreadLocalRef(..)
+            | Rvalue::Repeat(..)
+            | Rvalue::Len(..)
+            | Rvalue::BinaryOp(..)
+            | Rvalue::CheckedBinaryOp(..)
+            | Rvalue::NullaryOp(..)
+            | Rvalue::UnaryOp(..)
+            | Rvalue::Discriminant(..)
+            | Rvalue::Aggregate(..)
+            | Rvalue::CopyForDeref(..) => {}
         }
     }
 
-    fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) {
+    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
         self.super_terminator(terminator, location);
 
         match terminator.kind {
-            mir::TerminatorKind::Drop { place: dropped_place, .. } => {
+            TerminatorKind::Drop { place: dropped_place, .. } => {
                 // Drop terminators may call custom drop glue (`Drop::drop`), which takes `&mut
                 // self` as a parameter. In the general case, a drop impl could launder that
                 // reference into the surrounding environment through a raw pointer, thus creating
@@ -126,7 +131,7 @@ where
                 }
             }
 
-            TerminatorKind::Terminate
+            TerminatorKind::UnwindTerminate
             | TerminatorKind::Assert { .. }
             | TerminatorKind::Call { .. }
             | TerminatorKind::FalseEdge { .. }
@@ -134,7 +139,7 @@ where
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Goto { .. }
             | TerminatorKind::InlineAsm { .. }
-            | TerminatorKind::Resume
+            | TerminatorKind::UnwindResume
             | TerminatorKind::Return
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::Unreachable
diff --git a/compiler/rustc_mir_dataflow/src/impls/initialized.rs b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
new file mode 100644
index 00000000000..e6d383d626a
--- /dev/null
+++ b/compiler/rustc_mir_dataflow/src/impls/initialized.rs
@@ -0,0 +1,778 @@
+use rustc_index::bit_set::{BitSet, ChunkedBitSet};
+use rustc_index::Idx;
+use rustc_middle::mir::{self, Body, CallReturnPlaces, Location, TerminatorEdges};
+use rustc_middle::ty::{self, TyCtxt};
+
+use crate::drop_flag_effects_for_function_entry;
+use crate::drop_flag_effects_for_location;
+use crate::elaborate_drops::DropFlagState;
+use crate::framework::SwitchIntEdgeEffects;
+use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex};
+use crate::on_lookup_result_bits;
+use crate::MoveDataParamEnv;
+use crate::{drop_flag_effects, on_all_children_bits, on_all_drop_children_bits};
+use crate::{lattice, AnalysisDomain, GenKill, GenKillAnalysis, MaybeReachable};
+
+/// `MaybeInitializedPlaces` tracks all places that might be
+/// initialized upon reaching a particular point in the control flow
+/// for a function.
+///
+/// For example, in code like the following, we have corresponding
+/// dataflow information shown in the right-hand comments.
+///
+/// ```rust
+/// struct S;
+/// fn foo(pred: bool) {                        // maybe-init:
+///                                             // {}
+///     let a = S; let mut b = S; let c; let d; // {a, b}
+///
+///     if pred {
+///         drop(a);                            // {   b}
+///         b = S;                              // {   b}
+///
+///     } else {
+///         drop(b);                            // {a}
+///         d = S;                              // {a,       d}
+///
+///     }                                       // {a, b,    d}
+///
+///     c = S;                                  // {a, b, c, d}
+/// }
+/// ```
+///
+/// To determine whether a place *must* be initialized at a
+/// particular control-flow point, one can take the set-difference
+/// between this data and the data from `MaybeUninitializedPlaces` at the
+/// corresponding control-flow point.
+///
+/// Similarly, at a given `drop` statement, the set-intersection
+/// between this data and `MaybeUninitializedPlaces` yields the set of
+/// places that would require a dynamic drop-flag at that statement.
+pub struct MaybeInitializedPlaces<'a, 'tcx> {
+    tcx: TyCtxt<'tcx>,
+    body: &'a Body<'tcx>,
+    mdpe: &'a MoveDataParamEnv<'tcx>,
+    skip_unreachable_unwind: bool,
+}
+
+impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
+    pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
+        MaybeInitializedPlaces { tcx, body, mdpe, skip_unreachable_unwind: false }
+    }
+
+    pub fn skipping_unreachable_unwind(mut self) -> Self {
+        self.skip_unreachable_unwind = true;
+        self
+    }
+
+    pub fn is_unwind_dead(
+        &self,
+        place: mir::Place<'tcx>,
+        state: &MaybeReachable<ChunkedBitSet<MovePathIndex>>,
+    ) -> bool {
+        if let LookupResult::Exact(path) = self.move_data().rev_lookup.find(place.as_ref()) {
+            let mut maybe_live = false;
+            on_all_drop_children_bits(self.tcx, self.body, self.mdpe, path, |child| {
+                maybe_live |= state.contains(child);
+            });
+            !maybe_live
+        } else {
+            false
+        }
+    }
+}
+
+impl<'a, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'tcx> {
+    fn move_data(&self) -> &MoveData<'tcx> {
+        &self.mdpe.move_data
+    }
+}
+
+/// `MaybeUninitializedPlaces` tracks all places that might be
+/// uninitialized upon reaching a particular point in the control flow
+/// for a function.
+///
+/// For example, in code like the following, we have corresponding
+/// dataflow information shown in the right-hand comments.
+///
+/// ```rust
+/// struct S;
+/// fn foo(pred: bool) {                        // maybe-uninit:
+///                                             // {a, b, c, d}
+///     let a = S; let mut b = S; let c; let d; // {      c, d}
+///
+///     if pred {
+///         drop(a);                            // {a,    c, d}
+///         b = S;                              // {a,    c, d}
+///
+///     } else {
+///         drop(b);                            // {   b, c, d}
+///         d = S;                              // {   b, c   }
+///
+///     }                                       // {a, b, c, d}
+///
+///     c = S;                                  // {a, b,    d}
+/// }
+/// ```
+///
+/// To determine whether a place *must* be uninitialized at a
+/// particular control-flow point, one can take the set-difference
+/// between this data and the data from `MaybeInitializedPlaces` at the
+/// corresponding control-flow point.
+///
+/// Similarly, at a given `drop` statement, the set-intersection
+/// between this data and `MaybeInitializedPlaces` yields the set of
+/// places that would require a dynamic drop-flag at that statement.
+pub struct MaybeUninitializedPlaces<'a, 'tcx> {
+    tcx: TyCtxt<'tcx>,
+    body: &'a Body<'tcx>,
+    mdpe: &'a MoveDataParamEnv<'tcx>,
+
+    mark_inactive_variants_as_uninit: bool,
+    skip_unreachable_unwind: BitSet<mir::BasicBlock>,
+}
+
+impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
+    pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
+        MaybeUninitializedPlaces {
+            tcx,
+            body,
+            mdpe,
+            mark_inactive_variants_as_uninit: false,
+            skip_unreachable_unwind: BitSet::new_empty(body.basic_blocks.len()),
+        }
+    }
+
+    /// Causes inactive enum variants to be marked as "maybe uninitialized" after a switch on an
+    /// enum discriminant.
+    ///
+    /// This is correct in a vacuum but is not the default because it causes problems in the borrow
+    /// checker, where this information gets propagated along `FakeEdge`s.
+    pub fn mark_inactive_variants_as_uninit(mut self) -> Self {
+        self.mark_inactive_variants_as_uninit = true;
+        self
+    }
+
+    pub fn skipping_unreachable_unwind(
+        mut self,
+        unreachable_unwind: BitSet<mir::BasicBlock>,
+    ) -> Self {
+        self.skip_unreachable_unwind = unreachable_unwind;
+        self
+    }
+}
+
+impl<'a, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, 'tcx> {
+    fn move_data(&self) -> &MoveData<'tcx> {
+        &self.mdpe.move_data
+    }
+}
+
+/// `DefinitelyInitializedPlaces` tracks all places that are definitely
+/// initialized upon reaching a particular point in the control flow
+/// for a function.
+///
+/// For example, in code like the following, we have corresponding
+/// dataflow information shown in the right-hand comments.
+///
+/// ```rust
+/// struct S;
+/// fn foo(pred: bool) {                        // definite-init:
+///                                             // {          }
+///     let a = S; let mut b = S; let c; let d; // {a, b      }
+///
+///     if pred {
+///         drop(a);                            // {   b,     }
+///         b = S;                              // {   b,     }
+///
+///     } else {
+///         drop(b);                            // {a,        }
+///         d = S;                              // {a,       d}
+///
+///     }                                       // {          }
+///
+///     c = S;                                  // {       c  }
+/// }
+/// ```
+///
+/// To determine whether a place *may* be uninitialized at a
+/// particular control-flow point, one can take the set-complement
+/// of this data.
+///
+/// Similarly, at a given `drop` statement, the set-difference between
+/// this data and `MaybeInitializedPlaces` yields the set of places
+/// that would require a dynamic drop-flag at that statement.
+pub struct DefinitelyInitializedPlaces<'a, 'tcx> {
+    tcx: TyCtxt<'tcx>,
+    body: &'a Body<'tcx>,
+    mdpe: &'a MoveDataParamEnv<'tcx>,
+}
+
+impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> {
+    pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
+        DefinitelyInitializedPlaces { tcx, body, mdpe }
+    }
+}
+
+impl<'a, 'tcx> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
+    fn move_data(&self) -> &MoveData<'tcx> {
+        &self.mdpe.move_data
+    }
+}
+
+/// `EverInitializedPlaces` tracks all places that might have ever been
+/// initialized upon reaching a particular point in the control flow
+/// for a function, without an intervening `StorageDead`.
+///
+/// This dataflow is used to determine if an immutable local variable may
+/// be assigned to.
+///
+/// For example, in code like the following, we have corresponding
+/// dataflow information shown in the right-hand comments.
+///
+/// ```rust
+/// struct S;
+/// fn foo(pred: bool) {                        // ever-init:
+///                                             // {          }
+///     let a = S; let mut b = S; let c; let d; // {a, b      }
+///
+///     if pred {
+///         drop(a);                            // {a, b,     }
+///         b = S;                              // {a, b,     }
+///
+///     } else {
+///         drop(b);                            // {a, b,      }
+///         d = S;                              // {a, b,    d }
+///
+///     }                                       // {a, b,    d }
+///
+///     c = S;                                  // {a, b, c, d }
+/// }
+/// ```
+pub struct EverInitializedPlaces<'a, 'tcx> {
+    #[allow(dead_code)]
+    tcx: TyCtxt<'tcx>,
+    body: &'a Body<'tcx>,
+    mdpe: &'a MoveDataParamEnv<'tcx>,
+}
+
+impl<'a, 'tcx> EverInitializedPlaces<'a, 'tcx> {
+    pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
+        EverInitializedPlaces { tcx, body, mdpe }
+    }
+}
+
+impl<'a, 'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'a, 'tcx> {
+    fn move_data(&self) -> &MoveData<'tcx> {
+        &self.mdpe.move_data
+    }
+}
+
+impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
+    fn update_bits(
+        trans: &mut impl GenKill<MovePathIndex>,
+        path: MovePathIndex,
+        state: DropFlagState,
+    ) {
+        match state {
+            DropFlagState::Absent => trans.kill(path),
+            DropFlagState::Present => trans.gen(path),
+        }
+    }
+}
+
+impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
+    fn update_bits(
+        trans: &mut impl GenKill<MovePathIndex>,
+        path: MovePathIndex,
+        state: DropFlagState,
+    ) {
+        match state {
+            DropFlagState::Absent => trans.gen(path),
+            DropFlagState::Present => trans.kill(path),
+        }
+    }
+}
+
+impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> {
+    fn update_bits(
+        trans: &mut impl GenKill<MovePathIndex>,
+        path: MovePathIndex,
+        state: DropFlagState,
+    ) {
+        match state {
+            DropFlagState::Absent => trans.kill(path),
+            DropFlagState::Present => trans.gen(path),
+        }
+    }
+}
+
+impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
+    type Domain = MaybeReachable<ChunkedBitSet<MovePathIndex>>;
+    const NAME: &'static str = "maybe_init";
+
+    fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
+        // bottom = uninitialized
+        MaybeReachable::Unreachable
+    }
+
+    fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) {
+        *state =
+            MaybeReachable::Reachable(ChunkedBitSet::new_empty(self.move_data().move_paths.len()));
+        drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| {
+            assert!(s == DropFlagState::Present);
+            state.gen(path);
+        });
+    }
+}
+
+impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
+    type Idx = MovePathIndex;
+
+    fn domain_size(&self, _: &Body<'tcx>) -> usize {
+        self.move_data().move_paths.len()
+    }
+
+    fn statement_effect(
+        &mut self,
+        trans: &mut impl GenKill<Self::Idx>,
+        statement: &mir::Statement<'tcx>,
+        location: Location,
+    ) {
+        drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
+            Self::update_bits(trans, path, s)
+        });
+
+        // Mark all places as "maybe init" if they are mutably borrowed. See #90752.
+        if self.tcx.sess.opts.unstable_opts.precise_enum_drop_elaboration
+            && let Some((_, rvalue)) = statement.kind.as_assign()
+            && let mir::Rvalue::Ref(_, mir::BorrowKind::Mut { .. }, place)
+                // FIXME: Does `&raw const foo` allow mutation? See #90413.
+                | mir::Rvalue::AddressOf(_, place) = rvalue
+            && let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref())
+        {
+            on_all_children_bits(self.tcx, self.body, self.move_data(), mpi, |child| {
+                trans.gen(child);
+            })
+        }
+    }
+
+    fn terminator_effect<'mir>(
+        &mut self,
+        state: &mut Self::Domain,
+        terminator: &'mir mir::Terminator<'tcx>,
+        location: Location,
+    ) -> TerminatorEdges<'mir, 'tcx> {
+        let mut edges = terminator.edges();
+        if self.skip_unreachable_unwind
+            && let mir::TerminatorKind::Drop { target, unwind, place, replace: _ } = terminator.kind
+            && matches!(unwind, mir::UnwindAction::Cleanup(_))
+            && self.is_unwind_dead(place, state)
+        {
+            edges = TerminatorEdges::Single(target);
+        }
+        drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
+            Self::update_bits(state, path, s)
+        });
+        edges
+    }
+
+    fn call_return_effect(
+        &mut self,
+        trans: &mut impl GenKill<Self::Idx>,
+        _block: mir::BasicBlock,
+        return_places: CallReturnPlaces<'_, 'tcx>,
+    ) {
+        return_places.for_each(|place| {
+            // when a call returns successfully, that means we need to set
+            // the bits for that dest_place to 1 (initialized).
+            on_lookup_result_bits(
+                self.tcx,
+                self.body,
+                self.move_data(),
+                self.move_data().rev_lookup.find(place.as_ref()),
+                |mpi| {
+                    trans.gen(mpi);
+                },
+            );
+        });
+    }
+
+    fn switch_int_edge_effects<G: GenKill<Self::Idx>>(
+        &mut self,
+        block: mir::BasicBlock,
+        discr: &mir::Operand<'tcx>,
+        edge_effects: &mut impl SwitchIntEdgeEffects<G>,
+    ) {
+        if !self.tcx.sess.opts.unstable_opts.precise_enum_drop_elaboration {
+            return;
+        }
+
+        let enum_ = discr.place().and_then(|discr| {
+            switch_on_enum_discriminant(self.tcx, &self.body, &self.body[block], discr)
+        });
+
+        let Some((enum_place, enum_def)) = enum_ else {
+            return;
+        };
+
+        let mut discriminants = enum_def.discriminants(self.tcx);
+        edge_effects.apply(|trans, edge| {
+            let Some(value) = edge.value else {
+                return;
+            };
+
+            // MIR building adds discriminants to the `values` array in the same order as they
+            // are yielded by `AdtDef::discriminants`. We rely on this to match each
+            // discriminant in `values` to its corresponding variant in linear time.
+            let (variant, _) = discriminants
+                .find(|&(_, discr)| discr.val == value)
+                .expect("Order of `AdtDef::discriminants` differed from `SwitchInt::values`");
+
+            // Kill all move paths that correspond to variants we know to be inactive along this
+            // particular outgoing edge of a `SwitchInt`.
+            drop_flag_effects::on_all_inactive_variants(
+                self.tcx,
+                self.body,
+                self.move_data(),
+                enum_place,
+                variant,
+                |mpi| trans.kill(mpi),
+            );
+        });
+    }
+}
+
+impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
+    type Domain = ChunkedBitSet<MovePathIndex>;
+
+    const NAME: &'static str = "maybe_uninit";
+
+    fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
+        // bottom = initialized (start_block_effect counters this at outset)
+        ChunkedBitSet::new_empty(self.move_data().move_paths.len())
+    }
+
+    // sets on_entry bits for Arg places
+    fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) {
+        // set all bits to 1 (uninit) before gathering counter-evidence
+        state.insert_all();
+
+        drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| {
+            assert!(s == DropFlagState::Present);
+            state.remove(path);
+        });
+    }
+}
+
+impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
+    type Idx = MovePathIndex;
+
+    fn domain_size(&self, _: &Body<'tcx>) -> usize {
+        self.move_data().move_paths.len()
+    }
+
+    fn statement_effect(
+        &mut self,
+        trans: &mut impl GenKill<Self::Idx>,
+        _statement: &mir::Statement<'tcx>,
+        location: Location,
+    ) {
+        drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
+            Self::update_bits(trans, path, s)
+        });
+
+        // Unlike in `MaybeInitializedPlaces` above, we don't need to change the state when a
+        // mutable borrow occurs. Places cannot become uninitialized through a mutable reference.
+    }
+
+    fn terminator_effect<'mir>(
+        &mut self,
+        trans: &mut Self::Domain,
+        terminator: &'mir mir::Terminator<'tcx>,
+        location: Location,
+    ) -> TerminatorEdges<'mir, 'tcx> {
+        drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
+            Self::update_bits(trans, path, s)
+        });
+        if self.skip_unreachable_unwind.contains(location.block) {
+            let mir::TerminatorKind::Drop { target, unwind, .. } = terminator.kind else { bug!() };
+            assert!(matches!(unwind, mir::UnwindAction::Cleanup(_)));
+            TerminatorEdges::Single(target)
+        } else {
+            terminator.edges()
+        }
+    }
+
+    fn call_return_effect(
+        &mut self,
+        trans: &mut impl GenKill<Self::Idx>,
+        _block: mir::BasicBlock,
+        return_places: CallReturnPlaces<'_, 'tcx>,
+    ) {
+        return_places.for_each(|place| {
+            // when a call returns successfully, that means we need to set
+            // the bits for that dest_place to 0 (initialized).
+            on_lookup_result_bits(
+                self.tcx,
+                self.body,
+                self.move_data(),
+                self.move_data().rev_lookup.find(place.as_ref()),
+                |mpi| {
+                    trans.kill(mpi);
+                },
+            );
+        });
+    }
+
+    fn switch_int_edge_effects<G: GenKill<Self::Idx>>(
+        &mut self,
+        block: mir::BasicBlock,
+        discr: &mir::Operand<'tcx>,
+        edge_effects: &mut impl SwitchIntEdgeEffects<G>,
+    ) {
+        if !self.tcx.sess.opts.unstable_opts.precise_enum_drop_elaboration {
+            return;
+        }
+
+        if !self.mark_inactive_variants_as_uninit {
+            return;
+        }
+
+        let enum_ = discr.place().and_then(|discr| {
+            switch_on_enum_discriminant(self.tcx, &self.body, &self.body[block], discr)
+        });
+
+        let Some((enum_place, enum_def)) = enum_ else {
+            return;
+        };
+
+        let mut discriminants = enum_def.discriminants(self.tcx);
+        edge_effects.apply(|trans, edge| {
+            let Some(value) = edge.value else {
+                return;
+            };
+
+            // MIR building adds discriminants to the `values` array in the same order as they
+            // are yielded by `AdtDef::discriminants`. We rely on this to match each
+            // discriminant in `values` to its corresponding variant in linear time.
+            let (variant, _) = discriminants
+                .find(|&(_, discr)| discr.val == value)
+                .expect("Order of `AdtDef::discriminants` differed from `SwitchInt::values`");
+
+            // Mark all move paths that correspond to variants other than this one as maybe
+            // uninitialized (in reality, they are *definitely* uninitialized).
+            drop_flag_effects::on_all_inactive_variants(
+                self.tcx,
+                self.body,
+                self.move_data(),
+                enum_place,
+                variant,
+                |mpi| trans.gen(mpi),
+            );
+        });
+    }
+}
+
+impl<'a, 'tcx> AnalysisDomain<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
+    /// Use set intersection as the join operator.
+    type Domain = lattice::Dual<BitSet<MovePathIndex>>;
+
+    const NAME: &'static str = "definite_init";
+
+    fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
+        // bottom = initialized (start_block_effect counters this at outset)
+        lattice::Dual(BitSet::new_filled(self.move_data().move_paths.len()))
+    }
+
+    // sets on_entry bits for Arg places
+    fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) {
+        state.0.clear();
+
+        drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| {
+            assert!(s == DropFlagState::Present);
+            state.0.insert(path);
+        });
+    }
+}
+
+impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> {
+    type Idx = MovePathIndex;
+
+    fn domain_size(&self, _: &Body<'tcx>) -> usize {
+        self.move_data().move_paths.len()
+    }
+
+    fn statement_effect(
+        &mut self,
+        trans: &mut impl GenKill<Self::Idx>,
+        _statement: &mir::Statement<'tcx>,
+        location: Location,
+    ) {
+        drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
+            Self::update_bits(trans, path, s)
+        })
+    }
+
+    fn terminator_effect<'mir>(
+        &mut self,
+        trans: &mut Self::Domain,
+        terminator: &'mir mir::Terminator<'tcx>,
+        location: Location,
+    ) -> TerminatorEdges<'mir, 'tcx> {
+        drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
+            Self::update_bits(trans, path, s)
+        });
+        terminator.edges()
+    }
+
+    fn call_return_effect(
+        &mut self,
+        trans: &mut impl GenKill<Self::Idx>,
+        _block: mir::BasicBlock,
+        return_places: CallReturnPlaces<'_, 'tcx>,
+    ) {
+        return_places.for_each(|place| {
+            // when a call returns successfully, that means we need to set
+            // the bits for that dest_place to 1 (initialized).
+            on_lookup_result_bits(
+                self.tcx,
+                self.body,
+                self.move_data(),
+                self.move_data().rev_lookup.find(place.as_ref()),
+                |mpi| {
+                    trans.gen(mpi);
+                },
+            );
+        });
+    }
+}
+
+impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, 'tcx> {
+    type Domain = ChunkedBitSet<InitIndex>;
+
+    const NAME: &'static str = "ever_init";
+
+    fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
+        // bottom = no initialized variables by default
+        ChunkedBitSet::new_empty(self.move_data().inits.len())
+    }
+
+    fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut Self::Domain) {
+        for arg_init in 0..body.arg_count {
+            state.insert(InitIndex::new(arg_init));
+        }
+    }
+}
+
+impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
+    type Idx = InitIndex;
+
+    fn domain_size(&self, _: &Body<'tcx>) -> usize {
+        self.move_data().inits.len()
+    }
+
+    #[instrument(skip(self, trans), level = "debug")]
+    fn statement_effect(
+        &mut self,
+        trans: &mut impl GenKill<Self::Idx>,
+        stmt: &mir::Statement<'tcx>,
+        location: Location,
+    ) {
+        let move_data = self.move_data();
+        let init_path_map = &move_data.init_path_map;
+        let init_loc_map = &move_data.init_loc_map;
+        let rev_lookup = &move_data.rev_lookup;
+
+        debug!("initializes move_indexes {:?}", &init_loc_map[location]);
+        trans.gen_all(init_loc_map[location].iter().copied());
+
+        if let mir::StatementKind::StorageDead(local) = stmt.kind {
+            // End inits for StorageDead, so that an immutable variable can
+            // be reinitialized on the next iteration of the loop.
+            let move_path_index = rev_lookup.find_local(local);
+            debug!("clears the ever initialized status of {:?}", init_path_map[move_path_index]);
+            trans.kill_all(init_path_map[move_path_index].iter().copied());
+        }
+    }
+
+    #[instrument(skip(self, trans, terminator), level = "debug")]
+    fn terminator_effect<'mir>(
+        &mut self,
+        trans: &mut Self::Domain,
+        terminator: &'mir mir::Terminator<'tcx>,
+        location: Location,
+    ) -> TerminatorEdges<'mir, 'tcx> {
+        let (body, move_data) = (self.body, self.move_data());
+        let term = body[location.block].terminator();
+        let init_loc_map = &move_data.init_loc_map;
+        debug!(?term);
+        debug!("initializes move_indexes {:?}", init_loc_map[location]);
+        trans.gen_all(
+            init_loc_map[location]
+                .iter()
+                .filter(|init_index| {
+                    move_data.inits[**init_index].kind != InitKind::NonPanicPathOnly
+                })
+                .copied(),
+        );
+        terminator.edges()
+    }
+
+    fn call_return_effect(
+        &mut self,
+        trans: &mut impl GenKill<Self::Idx>,
+        block: mir::BasicBlock,
+        _return_places: CallReturnPlaces<'_, 'tcx>,
+    ) {
+        let move_data = self.move_data();
+        let init_loc_map = &move_data.init_loc_map;
+
+        let call_loc = self.body.terminator_loc(block);
+        for init_index in &init_loc_map[call_loc] {
+            trans.gen(*init_index);
+        }
+    }
+}
+
+/// Inspect a `SwitchInt`-terminated basic block to see if the condition of that `SwitchInt` is
+/// an enum discriminant.
+///
+/// We expect such blocks to have a call to `discriminant` as their last statement like so:
+///
+/// ```text
+/// ...
+/// _42 = discriminant(_1)
+/// SwitchInt(_42, ..)
+/// ```
+///
+/// If the basic block matches this pattern, this function returns the place corresponding to the
+/// enum (`_1` in the example above) as well as the `AdtDef` of that enum.
+fn switch_on_enum_discriminant<'mir, 'tcx>(
+    tcx: TyCtxt<'tcx>,
+    body: &'mir mir::Body<'tcx>,
+    block: &'mir mir::BasicBlockData<'tcx>,
+    switch_on: mir::Place<'tcx>,
+) -> Option<(mir::Place<'tcx>, ty::AdtDef<'tcx>)> {
+    for statement in block.statements.iter().rev() {
+        match &statement.kind {
+            mir::StatementKind::Assign(box (lhs, mir::Rvalue::Discriminant(discriminated)))
+                if *lhs == switch_on =>
+            {
+                match discriminated.ty(body, tcx).ty.kind() {
+                    ty::Adt(def, _) => return Some((*discriminated, *def)),
+
+                    // `Rvalue::Discriminant` is also used to get the active yield point for a
+                    // generator, but we do not need edge-specific effects in that case. This may
+                    // change in the future.
+                    ty::Generator(..) => return None,
+
+                    t => bug!("`discriminant` called on unexpected type {:?}", t),
+                }
+            }
+            mir::StatementKind::Coverage(_) => continue,
+            _ => return None,
+        }
+    }
+    None
+}
diff --git a/compiler/rustc_mir_dataflow/src/impls/liveness.rs b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
index 34e0834a68b..5aa73c7a906 100644
--- a/compiler/rustc_mir_dataflow/src/impls/liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/liveness.rs
@@ -1,8 +1,10 @@
 use rustc_index::bit_set::{BitSet, ChunkedBitSet};
 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
-use rustc_middle::mir::{self, Local, Location, Place, StatementKind};
+use rustc_middle::mir::{
+    self, CallReturnPlaces, Local, Location, Place, StatementKind, TerminatorEdges,
+};
 
-use crate::{Analysis, AnalysisDomain, Backward, CallReturnPlaces, GenKill, GenKillAnalysis};
+use crate::{Analysis, AnalysisDomain, Backward, GenKill, GenKillAnalysis};
 
 /// A [live-variable dataflow analysis][liveness].
 ///
@@ -43,6 +45,10 @@ impl<'tcx> AnalysisDomain<'tcx> for MaybeLiveLocals {
 impl<'tcx> GenKillAnalysis<'tcx> for MaybeLiveLocals {
     type Idx = Local;
 
+    fn domain_size(&self, body: &mir::Body<'tcx>) -> usize {
+        body.local_decls.len()
+    }
+
     fn statement_effect(
         &mut self,
         trans: &mut impl GenKill<Self::Idx>,
@@ -52,13 +58,14 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeLiveLocals {
         TransferFunction(trans).visit_statement(statement, location);
     }
 
-    fn terminator_effect(
+    fn terminator_effect<'mir>(
         &mut self,
-        trans: &mut impl GenKill<Self::Idx>,
-        terminator: &mir::Terminator<'tcx>,
+        trans: &mut Self::Domain,
+        terminator: &'mir mir::Terminator<'tcx>,
         location: Location,
-    ) {
+    ) -> TerminatorEdges<'mir, 'tcx> {
         TransferFunction(trans).visit_terminator(terminator, location);
+        terminator.edges()
     }
 
     fn call_return_effect(
@@ -67,24 +74,19 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeLiveLocals {
         _block: mir::BasicBlock,
         return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
-        return_places.for_each(|place| {
-            if let Some(local) = place.as_local() {
-                trans.kill(local);
-            }
-        });
-    }
-
-    fn yield_resume_effect(
-        &mut self,
-        trans: &mut impl GenKill<Self::Idx>,
-        _resume_block: mir::BasicBlock,
-        resume_place: mir::Place<'tcx>,
-    ) {
-        YieldResumeEffect(trans).visit_place(
-            &resume_place,
-            PlaceContext::MutatingUse(MutatingUseContext::Yield),
-            Location::START,
-        )
+        if let CallReturnPlaces::Yield(resume_place) = return_places {
+            YieldResumeEffect(trans).visit_place(
+                &resume_place,
+                PlaceContext::MutatingUse(MutatingUseContext::Yield),
+                Location::START,
+            )
+        } else {
+            return_places.for_each(|place| {
+                if let Some(local) = place.as_local() {
+                    trans.kill(local);
+                }
+            });
+        }
     }
 }
 
@@ -97,7 +99,7 @@ where
     fn visit_place(&mut self, place: &mir::Place<'tcx>, context: PlaceContext, location: Location) {
         if let PlaceContext::MutatingUse(MutatingUseContext::Yield) = context {
             // The resume place is evaluated and assigned to only after generator resumes, so its
-            // effect is handled separately in `yield_resume_effect`.
+            // effect is handled separately in `call_resume_effect`.
             return;
         }
 
@@ -283,13 +285,14 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
         TransferFunction(trans).visit_statement(statement, location);
     }
 
-    fn apply_terminator_effect(
+    fn apply_terminator_effect<'mir>(
         &mut self,
         trans: &mut Self::Domain,
-        terminator: &mir::Terminator<'tcx>,
+        terminator: &'mir mir::Terminator<'tcx>,
         location: Location,
-    ) {
+    ) -> TerminatorEdges<'mir, 'tcx> {
         TransferFunction(trans).visit_terminator(terminator, location);
+        terminator.edges()
     }
 
     fn apply_call_return_effect(
@@ -298,23 +301,18 @@ impl<'a, 'tcx> Analysis<'tcx> for MaybeTransitiveLiveLocals<'a> {
         _block: mir::BasicBlock,
         return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
-        return_places.for_each(|place| {
-            if let Some(local) = place.as_local() {
-                trans.remove(local);
-            }
-        });
-    }
-
-    fn apply_yield_resume_effect(
-        &mut self,
-        trans: &mut Self::Domain,
-        _resume_block: mir::BasicBlock,
-        resume_place: mir::Place<'tcx>,
-    ) {
-        YieldResumeEffect(trans).visit_place(
-            &resume_place,
-            PlaceContext::MutatingUse(MutatingUseContext::Yield),
-            Location::START,
-        )
+        if let CallReturnPlaces::Yield(resume_place) = return_places {
+            YieldResumeEffect(trans).visit_place(
+                &resume_place,
+                PlaceContext::MutatingUse(MutatingUseContext::Yield),
+                Location::START,
+            )
+        } else {
+            return_places.for_each(|place| {
+                if let Some(local) = place.as_local() {
+                    trans.remove(local);
+                }
+            });
+        }
     }
 }
diff --git a/compiler/rustc_mir_dataflow/src/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs
index 7ddd01e34aa..f8db18fc1f8 100644
--- a/compiler/rustc_mir_dataflow/src/impls/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs
@@ -2,768 +2,18 @@
 //! bitvectors attached to each basic block, represented via a
 //! zero-sized structure.
 
-use rustc_index::bit_set::{BitSet, ChunkedBitSet};
-use rustc_index::Idx;
-use rustc_middle::mir::visit::{MirVisitable, Visitor};
-use rustc_middle::mir::{self, Body, Location};
-use rustc_middle::ty::{self, TyCtxt};
-
-use crate::drop_flag_effects_for_function_entry;
-use crate::drop_flag_effects_for_location;
-use crate::elaborate_drops::DropFlagState;
-use crate::framework::{CallReturnPlaces, SwitchIntEdgeEffects};
-use crate::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex};
-use crate::on_lookup_result_bits;
-use crate::MoveDataParamEnv;
-use crate::{drop_flag_effects, on_all_children_bits};
-use crate::{lattice, AnalysisDomain, GenKill, GenKillAnalysis};
-
 mod borrowed_locals;
+mod initialized;
 mod liveness;
 mod storage_liveness;
 
 pub use self::borrowed_locals::borrowed_locals;
 pub use self::borrowed_locals::MaybeBorrowedLocals;
+pub use self::initialized::{
+    DefinitelyInitializedPlaces, EverInitializedPlaces, MaybeInitializedPlaces,
+    MaybeUninitializedPlaces,
+};
 pub use self::liveness::MaybeLiveLocals;
 pub use self::liveness::MaybeTransitiveLiveLocals;
 pub use self::liveness::TransferFunction as LivenessTransferFunction;
 pub use self::storage_liveness::{MaybeRequiresStorage, MaybeStorageDead, MaybeStorageLive};
-
-/// `MaybeInitializedPlaces` tracks all places that might be
-/// initialized upon reaching a particular point in the control flow
-/// for a function.
-///
-/// For example, in code like the following, we have corresponding
-/// dataflow information shown in the right-hand comments.
-///
-/// ```rust
-/// struct S;
-/// fn foo(pred: bool) {                        // maybe-init:
-///                                             // {}
-///     let a = S; let mut b = S; let c; let d; // {a, b}
-///
-///     if pred {
-///         drop(a);                            // {   b}
-///         b = S;                              // {   b}
-///
-///     } else {
-///         drop(b);                            // {a}
-///         d = S;                              // {a,       d}
-///
-///     }                                       // {a, b,    d}
-///
-///     c = S;                                  // {a, b, c, d}
-/// }
-/// ```
-///
-/// To determine whether a place *must* be initialized at a
-/// particular control-flow point, one can take the set-difference
-/// between this data and the data from `MaybeUninitializedPlaces` at the
-/// corresponding control-flow point.
-///
-/// Similarly, at a given `drop` statement, the set-intersection
-/// between this data and `MaybeUninitializedPlaces` yields the set of
-/// places that would require a dynamic drop-flag at that statement.
-pub struct MaybeInitializedPlaces<'a, 'tcx> {
-    tcx: TyCtxt<'tcx>,
-    body: &'a Body<'tcx>,
-    mdpe: &'a MoveDataParamEnv<'tcx>,
-}
-
-impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
-        MaybeInitializedPlaces { tcx, body, mdpe }
-    }
-}
-
-impl<'a, 'tcx> HasMoveData<'tcx> for MaybeInitializedPlaces<'a, 'tcx> {
-    fn move_data(&self) -> &MoveData<'tcx> {
-        &self.mdpe.move_data
-    }
-}
-
-/// `MaybeUninitializedPlaces` tracks all places that might be
-/// uninitialized upon reaching a particular point in the control flow
-/// for a function.
-///
-/// For example, in code like the following, we have corresponding
-/// dataflow information shown in the right-hand comments.
-///
-/// ```rust
-/// struct S;
-/// fn foo(pred: bool) {                        // maybe-uninit:
-///                                             // {a, b, c, d}
-///     let a = S; let mut b = S; let c; let d; // {      c, d}
-///
-///     if pred {
-///         drop(a);                            // {a,    c, d}
-///         b = S;                              // {a,    c, d}
-///
-///     } else {
-///         drop(b);                            // {   b, c, d}
-///         d = S;                              // {   b, c   }
-///
-///     }                                       // {a, b, c, d}
-///
-///     c = S;                                  // {a, b,    d}
-/// }
-/// ```
-///
-/// To determine whether a place *must* be uninitialized at a
-/// particular control-flow point, one can take the set-difference
-/// between this data and the data from `MaybeInitializedPlaces` at the
-/// corresponding control-flow point.
-///
-/// Similarly, at a given `drop` statement, the set-intersection
-/// between this data and `MaybeInitializedPlaces` yields the set of
-/// places that would require a dynamic drop-flag at that statement.
-pub struct MaybeUninitializedPlaces<'a, 'tcx> {
-    tcx: TyCtxt<'tcx>,
-    body: &'a Body<'tcx>,
-    mdpe: &'a MoveDataParamEnv<'tcx>,
-
-    mark_inactive_variants_as_uninit: bool,
-}
-
-impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
-        MaybeUninitializedPlaces { tcx, body, mdpe, mark_inactive_variants_as_uninit: false }
-    }
-
-    /// Causes inactive enum variants to be marked as "maybe uninitialized" after a switch on an
-    /// enum discriminant.
-    ///
-    /// This is correct in a vacuum but is not the default because it causes problems in the borrow
-    /// checker, where this information gets propagated along `FakeEdge`s.
-    pub fn mark_inactive_variants_as_uninit(mut self) -> Self {
-        self.mark_inactive_variants_as_uninit = true;
-        self
-    }
-}
-
-impl<'a, 'tcx> HasMoveData<'tcx> for MaybeUninitializedPlaces<'a, 'tcx> {
-    fn move_data(&self) -> &MoveData<'tcx> {
-        &self.mdpe.move_data
-    }
-}
-
-/// `DefinitelyInitializedPlaces` tracks all places that are definitely
-/// initialized upon reaching a particular point in the control flow
-/// for a function.
-///
-/// For example, in code like the following, we have corresponding
-/// dataflow information shown in the right-hand comments.
-///
-/// ```rust
-/// struct S;
-/// fn foo(pred: bool) {                        // definite-init:
-///                                             // {          }
-///     let a = S; let mut b = S; let c; let d; // {a, b      }
-///
-///     if pred {
-///         drop(a);                            // {   b,     }
-///         b = S;                              // {   b,     }
-///
-///     } else {
-///         drop(b);                            // {a,        }
-///         d = S;                              // {a,       d}
-///
-///     }                                       // {          }
-///
-///     c = S;                                  // {       c  }
-/// }
-/// ```
-///
-/// To determine whether a place *may* be uninitialized at a
-/// particular control-flow point, one can take the set-complement
-/// of this data.
-///
-/// Similarly, at a given `drop` statement, the set-difference between
-/// this data and `MaybeInitializedPlaces` yields the set of places
-/// that would require a dynamic drop-flag at that statement.
-pub struct DefinitelyInitializedPlaces<'a, 'tcx> {
-    tcx: TyCtxt<'tcx>,
-    body: &'a Body<'tcx>,
-    mdpe: &'a MoveDataParamEnv<'tcx>,
-}
-
-impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
-        DefinitelyInitializedPlaces { tcx, body, mdpe }
-    }
-}
-
-impl<'a, 'tcx> HasMoveData<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
-    fn move_data(&self) -> &MoveData<'tcx> {
-        &self.mdpe.move_data
-    }
-}
-
-/// `EverInitializedPlaces` tracks all places that might have ever been
-/// initialized upon reaching a particular point in the control flow
-/// for a function, without an intervening `StorageDead`.
-///
-/// This dataflow is used to determine if an immutable local variable may
-/// be assigned to.
-///
-/// For example, in code like the following, we have corresponding
-/// dataflow information shown in the right-hand comments.
-///
-/// ```rust
-/// struct S;
-/// fn foo(pred: bool) {                        // ever-init:
-///                                             // {          }
-///     let a = S; let mut b = S; let c; let d; // {a, b      }
-///
-///     if pred {
-///         drop(a);                            // {a, b,     }
-///         b = S;                              // {a, b,     }
-///
-///     } else {
-///         drop(b);                            // {a, b,      }
-///         d = S;                              // {a, b,    d }
-///
-///     }                                       // {a, b,    d }
-///
-///     c = S;                                  // {a, b, c, d }
-/// }
-/// ```
-pub struct EverInitializedPlaces<'a, 'tcx> {
-    #[allow(dead_code)]
-    tcx: TyCtxt<'tcx>,
-    body: &'a Body<'tcx>,
-    mdpe: &'a MoveDataParamEnv<'tcx>,
-}
-
-impl<'a, 'tcx> EverInitializedPlaces<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, mdpe: &'a MoveDataParamEnv<'tcx>) -> Self {
-        EverInitializedPlaces { tcx, body, mdpe }
-    }
-}
-
-impl<'a, 'tcx> HasMoveData<'tcx> for EverInitializedPlaces<'a, 'tcx> {
-    fn move_data(&self) -> &MoveData<'tcx> {
-        &self.mdpe.move_data
-    }
-}
-
-impl<'a, 'tcx> MaybeInitializedPlaces<'a, 'tcx> {
-    fn update_bits(
-        trans: &mut impl GenKill<MovePathIndex>,
-        path: MovePathIndex,
-        state: DropFlagState,
-    ) {
-        match state {
-            DropFlagState::Absent => trans.kill(path),
-            DropFlagState::Present => trans.gen(path),
-        }
-    }
-}
-
-impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
-    fn update_bits(
-        trans: &mut impl GenKill<MovePathIndex>,
-        path: MovePathIndex,
-        state: DropFlagState,
-    ) {
-        match state {
-            DropFlagState::Absent => trans.gen(path),
-            DropFlagState::Present => trans.kill(path),
-        }
-    }
-}
-
-impl<'a, 'tcx> DefinitelyInitializedPlaces<'a, 'tcx> {
-    fn update_bits(
-        trans: &mut impl GenKill<MovePathIndex>,
-        path: MovePathIndex,
-        state: DropFlagState,
-    ) {
-        match state {
-            DropFlagState::Absent => trans.kill(path),
-            DropFlagState::Present => trans.gen(path),
-        }
-    }
-}
-
-impl<'tcx> AnalysisDomain<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
-    type Domain = ChunkedBitSet<MovePathIndex>;
-    const NAME: &'static str = "maybe_init";
-
-    fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
-        // bottom = uninitialized
-        ChunkedBitSet::new_empty(self.move_data().move_paths.len())
-    }
-
-    fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) {
-        drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| {
-            assert!(s == DropFlagState::Present);
-            state.insert(path);
-        });
-    }
-}
-
-impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> {
-    type Idx = MovePathIndex;
-
-    fn statement_effect(
-        &mut self,
-        trans: &mut impl GenKill<Self::Idx>,
-        statement: &mir::Statement<'tcx>,
-        location: Location,
-    ) {
-        drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
-            Self::update_bits(trans, path, s)
-        });
-
-        if !self.tcx.sess.opts.unstable_opts.precise_enum_drop_elaboration {
-            return;
-        }
-
-        // Mark all places as "maybe init" if they are mutably borrowed. See #90752.
-        for_each_mut_borrow(statement, location, |place| {
-            let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref()) else {
-                return;
-            };
-            on_all_children_bits(self.tcx, self.body, self.move_data(), mpi, |child| {
-                trans.gen(child);
-            })
-        })
-    }
-
-    fn terminator_effect(
-        &mut self,
-        trans: &mut impl GenKill<Self::Idx>,
-        terminator: &mir::Terminator<'tcx>,
-        location: Location,
-    ) {
-        drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
-            Self::update_bits(trans, path, s)
-        });
-
-        if !self.tcx.sess.opts.unstable_opts.precise_enum_drop_elaboration {
-            return;
-        }
-
-        for_each_mut_borrow(terminator, location, |place| {
-            let LookupResult::Exact(mpi) = self.move_data().rev_lookup.find(place.as_ref()) else {
-                return;
-            };
-            on_all_children_bits(self.tcx, self.body, self.move_data(), mpi, |child| {
-                trans.gen(child);
-            })
-        })
-    }
-
-    fn call_return_effect(
-        &mut self,
-        trans: &mut impl GenKill<Self::Idx>,
-        _block: mir::BasicBlock,
-        return_places: CallReturnPlaces<'_, 'tcx>,
-    ) {
-        return_places.for_each(|place| {
-            // when a call returns successfully, that means we need to set
-            // the bits for that dest_place to 1 (initialized).
-            on_lookup_result_bits(
-                self.tcx,
-                self.body,
-                self.move_data(),
-                self.move_data().rev_lookup.find(place.as_ref()),
-                |mpi| {
-                    trans.gen(mpi);
-                },
-            );
-        });
-    }
-
-    fn switch_int_edge_effects<G: GenKill<Self::Idx>>(
-        &mut self,
-        block: mir::BasicBlock,
-        discr: &mir::Operand<'tcx>,
-        edge_effects: &mut impl SwitchIntEdgeEffects<G>,
-    ) {
-        if !self.tcx.sess.opts.unstable_opts.precise_enum_drop_elaboration {
-            return;
-        }
-
-        let enum_ = discr.place().and_then(|discr| {
-            switch_on_enum_discriminant(self.tcx, &self.body, &self.body[block], discr)
-        });
-
-        let Some((enum_place, enum_def)) = enum_ else {
-            return;
-        };
-
-        let mut discriminants = enum_def.discriminants(self.tcx);
-        edge_effects.apply(|trans, edge| {
-            let Some(value) = edge.value else {
-                return;
-            };
-
-            // MIR building adds discriminants to the `values` array in the same order as they
-            // are yielded by `AdtDef::discriminants`. We rely on this to match each
-            // discriminant in `values` to its corresponding variant in linear time.
-            let (variant, _) = discriminants
-                .find(|&(_, discr)| discr.val == value)
-                .expect("Order of `AdtDef::discriminants` differed from `SwitchInt::values`");
-
-            // Kill all move paths that correspond to variants we know to be inactive along this
-            // particular outgoing edge of a `SwitchInt`.
-            drop_flag_effects::on_all_inactive_variants(
-                self.tcx,
-                self.body,
-                self.move_data(),
-                enum_place,
-                variant,
-                |mpi| trans.kill(mpi),
-            );
-        });
-    }
-}
-
-impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
-    type Domain = ChunkedBitSet<MovePathIndex>;
-
-    const NAME: &'static str = "maybe_uninit";
-
-    fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
-        // bottom = initialized (start_block_effect counters this at outset)
-        ChunkedBitSet::new_empty(self.move_data().move_paths.len())
-    }
-
-    // sets on_entry bits for Arg places
-    fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) {
-        // set all bits to 1 (uninit) before gathering counter-evidence
-        state.insert_all();
-
-        drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| {
-            assert!(s == DropFlagState::Present);
-            state.remove(path);
-        });
-    }
-}
-
-impl<'tcx> GenKillAnalysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
-    type Idx = MovePathIndex;
-
-    fn statement_effect(
-        &mut self,
-        trans: &mut impl GenKill<Self::Idx>,
-        _statement: &mir::Statement<'tcx>,
-        location: Location,
-    ) {
-        drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
-            Self::update_bits(trans, path, s)
-        });
-
-        // Unlike in `MaybeInitializedPlaces` above, we don't need to change the state when a
-        // mutable borrow occurs. Places cannot become uninitialized through a mutable reference.
-    }
-
-    fn terminator_effect(
-        &mut self,
-        trans: &mut impl GenKill<Self::Idx>,
-        _terminator: &mir::Terminator<'tcx>,
-        location: Location,
-    ) {
-        drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
-            Self::update_bits(trans, path, s)
-        });
-    }
-
-    fn call_return_effect(
-        &mut self,
-        trans: &mut impl GenKill<Self::Idx>,
-        _block: mir::BasicBlock,
-        return_places: CallReturnPlaces<'_, 'tcx>,
-    ) {
-        return_places.for_each(|place| {
-            // when a call returns successfully, that means we need to set
-            // the bits for that dest_place to 0 (initialized).
-            on_lookup_result_bits(
-                self.tcx,
-                self.body,
-                self.move_data(),
-                self.move_data().rev_lookup.find(place.as_ref()),
-                |mpi| {
-                    trans.kill(mpi);
-                },
-            );
-        });
-    }
-
-    fn switch_int_edge_effects<G: GenKill<Self::Idx>>(
-        &mut self,
-        block: mir::BasicBlock,
-        discr: &mir::Operand<'tcx>,
-        edge_effects: &mut impl SwitchIntEdgeEffects<G>,
-    ) {
-        if !self.tcx.sess.opts.unstable_opts.precise_enum_drop_elaboration {
-            return;
-        }
-
-        if !self.mark_inactive_variants_as_uninit {
-            return;
-        }
-
-        let enum_ = discr.place().and_then(|discr| {
-            switch_on_enum_discriminant(self.tcx, &self.body, &self.body[block], discr)
-        });
-
-        let Some((enum_place, enum_def)) = enum_ else {
-            return;
-        };
-
-        let mut discriminants = enum_def.discriminants(self.tcx);
-        edge_effects.apply(|trans, edge| {
-            let Some(value) = edge.value else {
-                return;
-            };
-
-            // MIR building adds discriminants to the `values` array in the same order as they
-            // are yielded by `AdtDef::discriminants`. We rely on this to match each
-            // discriminant in `values` to its corresponding variant in linear time.
-            let (variant, _) = discriminants
-                .find(|&(_, discr)| discr.val == value)
-                .expect("Order of `AdtDef::discriminants` differed from `SwitchInt::values`");
-
-            // Mark all move paths that correspond to variants other than this one as maybe
-            // uninitialized (in reality, they are *definitely* uninitialized).
-            drop_flag_effects::on_all_inactive_variants(
-                self.tcx,
-                self.body,
-                self.move_data(),
-                enum_place,
-                variant,
-                |mpi| trans.gen(mpi),
-            );
-        });
-    }
-}
-
-impl<'a, 'tcx> AnalysisDomain<'tcx> for DefinitelyInitializedPlaces<'a, 'tcx> {
-    /// Use set intersection as the join operator.
-    type Domain = lattice::Dual<BitSet<MovePathIndex>>;
-
-    const NAME: &'static str = "definite_init";
-
-    fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
-        // bottom = initialized (start_block_effect counters this at outset)
-        lattice::Dual(BitSet::new_filled(self.move_data().move_paths.len()))
-    }
-
-    // sets on_entry bits for Arg places
-    fn initialize_start_block(&self, _: &mir::Body<'tcx>, state: &mut Self::Domain) {
-        state.0.clear();
-
-        drop_flag_effects_for_function_entry(self.tcx, self.body, self.mdpe, |path, s| {
-            assert!(s == DropFlagState::Present);
-            state.0.insert(path);
-        });
-    }
-}
-
-impl<'tcx> GenKillAnalysis<'tcx> for DefinitelyInitializedPlaces<'_, 'tcx> {
-    type Idx = MovePathIndex;
-
-    fn statement_effect(
-        &mut self,
-        trans: &mut impl GenKill<Self::Idx>,
-        _statement: &mir::Statement<'tcx>,
-        location: Location,
-    ) {
-        drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
-            Self::update_bits(trans, path, s)
-        })
-    }
-
-    fn terminator_effect(
-        &mut self,
-        trans: &mut impl GenKill<Self::Idx>,
-        _terminator: &mir::Terminator<'tcx>,
-        location: Location,
-    ) {
-        drop_flag_effects_for_location(self.tcx, self.body, self.mdpe, location, |path, s| {
-            Self::update_bits(trans, path, s)
-        })
-    }
-
-    fn call_return_effect(
-        &mut self,
-        trans: &mut impl GenKill<Self::Idx>,
-        _block: mir::BasicBlock,
-        return_places: CallReturnPlaces<'_, 'tcx>,
-    ) {
-        return_places.for_each(|place| {
-            // when a call returns successfully, that means we need to set
-            // the bits for that dest_place to 1 (initialized).
-            on_lookup_result_bits(
-                self.tcx,
-                self.body,
-                self.move_data(),
-                self.move_data().rev_lookup.find(place.as_ref()),
-                |mpi| {
-                    trans.gen(mpi);
-                },
-            );
-        });
-    }
-}
-
-impl<'tcx> AnalysisDomain<'tcx> for EverInitializedPlaces<'_, 'tcx> {
-    type Domain = ChunkedBitSet<InitIndex>;
-
-    const NAME: &'static str = "ever_init";
-
-    fn bottom_value(&self, _: &mir::Body<'tcx>) -> Self::Domain {
-        // bottom = no initialized variables by default
-        ChunkedBitSet::new_empty(self.move_data().inits.len())
-    }
-
-    fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut Self::Domain) {
-        for arg_init in 0..body.arg_count {
-            state.insert(InitIndex::new(arg_init));
-        }
-    }
-}
-
-impl<'tcx> GenKillAnalysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
-    type Idx = InitIndex;
-
-    #[instrument(skip(self, trans), level = "debug")]
-    fn statement_effect(
-        &mut self,
-        trans: &mut impl GenKill<Self::Idx>,
-        stmt: &mir::Statement<'tcx>,
-        location: Location,
-    ) {
-        let move_data = self.move_data();
-        let init_path_map = &move_data.init_path_map;
-        let init_loc_map = &move_data.init_loc_map;
-        let rev_lookup = &move_data.rev_lookup;
-
-        debug!("initializes move_indexes {:?}", &init_loc_map[location]);
-        trans.gen_all(init_loc_map[location].iter().copied());
-
-        if let mir::StatementKind::StorageDead(local) = stmt.kind {
-            // End inits for StorageDead, so that an immutable variable can
-            // be reinitialized on the next iteration of the loop.
-            let move_path_index = rev_lookup.find_local(local);
-            debug!("clears the ever initialized status of {:?}", init_path_map[move_path_index]);
-            trans.kill_all(init_path_map[move_path_index].iter().copied());
-        }
-    }
-
-    #[instrument(skip(self, trans, _terminator), level = "debug")]
-    fn terminator_effect(
-        &mut self,
-        trans: &mut impl GenKill<Self::Idx>,
-        _terminator: &mir::Terminator<'tcx>,
-        location: Location,
-    ) {
-        let (body, move_data) = (self.body, self.move_data());
-        let term = body[location.block].terminator();
-        let init_loc_map = &move_data.init_loc_map;
-        debug!(?term);
-        debug!("initializes move_indexes {:?}", init_loc_map[location]);
-        trans.gen_all(
-            init_loc_map[location]
-                .iter()
-                .filter(|init_index| {
-                    move_data.inits[**init_index].kind != InitKind::NonPanicPathOnly
-                })
-                .copied(),
-        );
-    }
-
-    fn call_return_effect(
-        &mut self,
-        trans: &mut impl GenKill<Self::Idx>,
-        block: mir::BasicBlock,
-        _return_places: CallReturnPlaces<'_, 'tcx>,
-    ) {
-        let move_data = self.move_data();
-        let init_loc_map = &move_data.init_loc_map;
-
-        let call_loc = self.body.terminator_loc(block);
-        for init_index in &init_loc_map[call_loc] {
-            trans.gen(*init_index);
-        }
-    }
-}
-
-/// Inspect a `SwitchInt`-terminated basic block to see if the condition of that `SwitchInt` is
-/// an enum discriminant.
-///
-/// We expect such blocks to have a call to `discriminant` as their last statement like so:
-///
-/// ```text
-/// ...
-/// _42 = discriminant(_1)
-/// SwitchInt(_42, ..)
-/// ```
-///
-/// If the basic block matches this pattern, this function returns the place corresponding to the
-/// enum (`_1` in the example above) as well as the `AdtDef` of that enum.
-fn switch_on_enum_discriminant<'mir, 'tcx>(
-    tcx: TyCtxt<'tcx>,
-    body: &'mir mir::Body<'tcx>,
-    block: &'mir mir::BasicBlockData<'tcx>,
-    switch_on: mir::Place<'tcx>,
-) -> Option<(mir::Place<'tcx>, ty::AdtDef<'tcx>)> {
-    for statement in block.statements.iter().rev() {
-        match &statement.kind {
-            mir::StatementKind::Assign(box (lhs, mir::Rvalue::Discriminant(discriminated)))
-                if *lhs == switch_on =>
-            {
-                match discriminated.ty(body, tcx).ty.kind() {
-                    ty::Adt(def, _) => return Some((*discriminated, *def)),
-
-                    // `Rvalue::Discriminant` is also used to get the active yield point for a
-                    // generator, but we do not need edge-specific effects in that case. This may
-                    // change in the future.
-                    ty::Generator(..) => return None,
-
-                    t => bug!("`discriminant` called on unexpected type {:?}", t),
-                }
-            }
-            mir::StatementKind::Coverage(_) => continue,
-            _ => return None,
-        }
-    }
-    None
-}
-
-struct OnMutBorrow<F>(F);
-
-impl<'tcx, F> Visitor<'tcx> for OnMutBorrow<F>
-where
-    F: FnMut(&mir::Place<'tcx>),
-{
-    fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
-        // FIXME: Does `&raw const foo` allow mutation? See #90413.
-        match rvalue {
-            mir::Rvalue::Ref(_, mir::BorrowKind::Mut { .. }, place)
-            | mir::Rvalue::AddressOf(_, place) => (self.0)(place),
-
-            _ => {}
-        }
-
-        self.super_rvalue(rvalue, location)
-    }
-}
-
-/// Calls `f` for each mutable borrow or raw reference in the program.
-///
-/// This DOES NOT call `f` for a shared borrow of a type with interior mutability. That's okay for
-/// initializedness, because we cannot move from an `UnsafeCell` (outside of `core::cell`), but
-/// other analyses will likely need to check for `!Freeze`.
-fn for_each_mut_borrow<'tcx>(
-    mir: &impl MirVisitable<'tcx>,
-    location: Location,
-    f: impl FnMut(&mir::Place<'tcx>),
-) {
-    let mut vis = OnMutBorrow(f);
-
-    mir.apply(location, &mut vis);
-}
diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
index 666c8d50a8a..531390c2f07 100644
--- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
@@ -1,10 +1,12 @@
-pub use super::*;
-
-use crate::{CallReturnPlaces, GenKill, ResultsClonedCursor};
+use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::*;
+
 use std::borrow::Cow;
 
+use super::MaybeBorrowedLocals;
+use crate::{GenKill, ResultsClonedCursor};
+
 #[derive(Clone)]
 pub struct MaybeStorageLive<'a> {
     always_live_locals: Cow<'a, BitSet<Local>>,
@@ -27,12 +29,12 @@ impl<'tcx, 'a> crate::AnalysisDomain<'tcx> for MaybeStorageLive<'a> {
 
     const NAME: &'static str = "maybe_storage_live";
 
-    fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
+    fn bottom_value(&self, body: &Body<'tcx>) -> Self::Domain {
         // bottom = dead
         BitSet::new_empty(body.local_decls.len())
     }
 
-    fn initialize_start_block(&self, body: &mir::Body<'tcx>, on_entry: &mut Self::Domain) {
+    fn initialize_start_block(&self, body: &Body<'tcx>, on_entry: &mut Self::Domain) {
         assert_eq!(body.local_decls.len(), self.always_live_locals.domain_size());
         for local in self.always_live_locals.iter() {
             on_entry.insert(local);
@@ -47,10 +49,14 @@ impl<'tcx, 'a> crate::AnalysisDomain<'tcx> for MaybeStorageLive<'a> {
 impl<'tcx, 'a> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> {
     type Idx = Local;
 
+    fn domain_size(&self, body: &Body<'tcx>) -> usize {
+        body.local_decls.len()
+    }
+
     fn statement_effect(
         &mut self,
         trans: &mut impl GenKill<Self::Idx>,
-        stmt: &mir::Statement<'tcx>,
+        stmt: &Statement<'tcx>,
         _: Location,
     ) {
         match stmt.kind {
@@ -60,13 +66,14 @@ impl<'tcx, 'a> crate::GenKillAnalysis<'tcx> for MaybeStorageLive<'a> {
         }
     }
 
-    fn terminator_effect(
+    fn terminator_effect<'mir>(
         &mut self,
-        _trans: &mut impl GenKill<Self::Idx>,
-        _: &mir::Terminator<'tcx>,
+        _trans: &mut Self::Domain,
+        terminator: &'mir Terminator<'tcx>,
         _: Location,
-    ) {
+    ) -> TerminatorEdges<'mir, 'tcx> {
         // Terminators have no effect
+        terminator.edges()
     }
 
     fn call_return_effect(
@@ -95,12 +102,12 @@ impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeStorageDead {
 
     const NAME: &'static str = "maybe_storage_dead";
 
-    fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
+    fn bottom_value(&self, body: &Body<'tcx>) -> Self::Domain {
         // bottom = live
         BitSet::new_empty(body.local_decls.len())
     }
 
-    fn initialize_start_block(&self, body: &mir::Body<'tcx>, on_entry: &mut Self::Domain) {
+    fn initialize_start_block(&self, body: &Body<'tcx>, on_entry: &mut Self::Domain) {
         assert_eq!(body.local_decls.len(), self.always_live_locals.domain_size());
         // Do not iterate on return place and args, as they are trivially always live.
         for local in body.vars_and_temps_iter() {
@@ -114,10 +121,14 @@ impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeStorageDead {
 impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageDead {
     type Idx = Local;
 
+    fn domain_size(&self, body: &Body<'tcx>) -> usize {
+        body.local_decls.len()
+    }
+
     fn statement_effect(
         &mut self,
         trans: &mut impl GenKill<Self::Idx>,
-        stmt: &mir::Statement<'tcx>,
+        stmt: &Statement<'tcx>,
         _: Location,
     ) {
         match stmt.kind {
@@ -127,13 +138,14 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeStorageDead {
         }
     }
 
-    fn terminator_effect(
+    fn terminator_effect<'mir>(
         &mut self,
-        _trans: &mut impl GenKill<Self::Idx>,
-        _: &mir::Terminator<'tcx>,
+        _: &mut Self::Domain,
+        terminator: &'mir Terminator<'tcx>,
         _: Location,
-    ) {
+    ) -> TerminatorEdges<'mir, 'tcx> {
         // Terminators have no effect
+        terminator.edges()
     }
 
     fn call_return_effect(
@@ -172,12 +184,12 @@ impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
 
     const NAME: &'static str = "requires_storage";
 
-    fn bottom_value(&self, body: &mir::Body<'tcx>) -> Self::Domain {
+    fn bottom_value(&self, body: &Body<'tcx>) -> Self::Domain {
         // bottom = dead
         BitSet::new_empty(body.local_decls.len())
     }
 
-    fn initialize_start_block(&self, body: &mir::Body<'tcx>, on_entry: &mut Self::Domain) {
+    fn initialize_start_block(&self, body: &Body<'tcx>, on_entry: &mut Self::Domain) {
         // The resume argument is live on function entry (we don't care about
         // the `self` argument)
         for arg in body.args_iter().skip(1) {
@@ -189,10 +201,14 @@ impl<'tcx> crate::AnalysisDomain<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
 impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
     type Idx = Local;
 
+    fn domain_size(&self, body: &Body<'tcx>) -> usize {
+        body.local_decls.len()
+    }
+
     fn before_statement_effect(
         &mut self,
         trans: &mut impl GenKill<Self::Idx>,
-        stmt: &mir::Statement<'tcx>,
+        stmt: &Statement<'tcx>,
         loc: Location,
     ) {
         // If a place is borrowed in a statement, it needs storage for that statement.
@@ -225,7 +241,7 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
     fn statement_effect(
         &mut self,
         trans: &mut impl GenKill<Self::Idx>,
-        _: &mir::Statement<'tcx>,
+        _: &Statement<'tcx>,
         loc: Location,
     ) {
         // If we move from a place then it only stops needing storage *after*
@@ -236,11 +252,14 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
     fn before_terminator_effect(
         &mut self,
         trans: &mut impl GenKill<Self::Idx>,
-        terminator: &mir::Terminator<'tcx>,
+        terminator: &Terminator<'tcx>,
         loc: Location,
     ) {
         // If a place is borrowed in a terminator, it needs storage for that terminator.
-        self.borrowed_locals.mut_analysis().terminator_effect(trans, terminator, loc);
+        self.borrowed_locals
+            .mut_analysis()
+            .transfer_function(trans)
+            .visit_terminator(terminator, loc);
 
         match &terminator.kind {
             TerminatorKind::Call { destination, .. } => {
@@ -272,26 +291,26 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
 
             // Nothing to do for these. Match exhaustively so this fails to compile when new
             // variants are added.
-            TerminatorKind::Terminate
+            TerminatorKind::UnwindTerminate
             | TerminatorKind::Assert { .. }
             | TerminatorKind::Drop { .. }
             | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. }
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
+            | TerminatorKind::UnwindResume
             | TerminatorKind::Return
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::Unreachable => {}
         }
     }
 
-    fn terminator_effect(
+    fn terminator_effect<'t>(
         &mut self,
-        trans: &mut impl GenKill<Self::Idx>,
-        terminator: &mir::Terminator<'tcx>,
+        trans: &mut Self::Domain,
+        terminator: &'t Terminator<'tcx>,
         loc: Location,
-    ) {
+    ) -> TerminatorEdges<'t, 'tcx> {
         match terminator.kind {
             // For call terminators the destination requires storage for the call
             // and after the call returns successfully, but not after a panic.
@@ -309,20 +328,21 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
             // Nothing to do for these. Match exhaustively so this fails to compile when new
             // variants are added.
             TerminatorKind::Yield { .. }
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Assert { .. }
             | TerminatorKind::Drop { .. }
             | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. }
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
+            | TerminatorKind::UnwindResume
             | TerminatorKind::Return
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::Unreachable => {}
         }
 
         self.check_for_move(trans, loc);
+        terminator.edges()
     }
 
     fn call_return_effect(
@@ -333,15 +353,6 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
     ) {
         return_places.for_each(|place| trans.gen(place.local));
     }
-
-    fn yield_resume_effect(
-        &mut self,
-        trans: &mut impl GenKill<Self::Idx>,
-        _resume_block: BasicBlock,
-        resume_place: mir::Place<'tcx>,
-    ) {
-        trans.gen(resume_place.local);
-    }
 }
 
 impl<'tcx> MaybeRequiresStorage<'_, '_, 'tcx> {
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index 900d438f8d5..0cdbee19d2c 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -28,8 +28,8 @@ pub use self::drop_flag_effects::{
 };
 pub use self::framework::{
     fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, AnalysisResults, Backward,
-    CallReturnPlaces, CloneAnalysis, Direction, Engine, Forward, GenKill, GenKillAnalysis,
-    JoinSemiLattice, Results, ResultsCloned, ResultsClonedCursor, ResultsCursor, ResultsRefCursor,
+    CloneAnalysis, Direction, Engine, Forward, GenKill, GenKillAnalysis, JoinSemiLattice,
+    MaybeReachable, Results, ResultsCloned, ResultsClonedCursor, ResultsCursor, ResultsRefCursor,
     ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects,
 };
 
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index 5052de99184..4adf3dec61b 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -370,8 +370,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
             // this that could possibly access the return place, this doesn't
             // need recording.
             | TerminatorKind::Return
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Unreachable
             | TerminatorKind::Drop { .. } => {}
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index 17bb8fc37ad..1eea8eef0ad 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -47,8 +47,7 @@ use rustc_target::abi::{FieldIdx, VariantIdx};
 
 use crate::lattice::{HasBottom, HasTop};
 use crate::{
-    fmt::DebugWithContext, Analysis, AnalysisDomain, CallReturnPlaces, JoinSemiLattice,
-    SwitchIntEdgeEffects,
+    fmt::DebugWithContext, Analysis, AnalysisDomain, JoinSemiLattice, SwitchIntEdgeEffects,
 };
 
 pub trait ValueAnalysis<'tcx> {
@@ -242,11 +241,19 @@ pub trait ValueAnalysis<'tcx> {
 
     /// The effect of a successful function call return should not be
     /// applied here, see [`Analysis::apply_terminator_effect`].
-    fn handle_terminator(&self, terminator: &Terminator<'tcx>, state: &mut State<Self::Value>) {
+    fn handle_terminator<'mir>(
+        &self,
+        terminator: &'mir Terminator<'tcx>,
+        state: &mut State<Self::Value>,
+    ) -> TerminatorEdges<'mir, 'tcx> {
         self.super_terminator(terminator, state)
     }
 
-    fn super_terminator(&self, terminator: &Terminator<'tcx>, state: &mut State<Self::Value>) {
+    fn super_terminator<'mir>(
+        &self,
+        terminator: &'mir Terminator<'tcx>,
+        state: &mut State<Self::Value>,
+    ) -> TerminatorEdges<'mir, 'tcx> {
         match &terminator.kind {
             TerminatorKind::Call { .. } | TerminatorKind::InlineAsm { .. } => {
                 // Effect is applied by `handle_call_return`.
@@ -258,10 +265,12 @@ pub trait ValueAnalysis<'tcx> {
                 // They would have an effect, but are not allowed in this phase.
                 bug!("encountered disallowed terminator");
             }
+            TerminatorKind::SwitchInt { discr, targets } => {
+                return self.handle_switch_int(discr, targets, state);
+            }
             TerminatorKind::Goto { .. }
-            | TerminatorKind::SwitchInt { .. }
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::Assert { .. }
@@ -271,6 +280,7 @@ pub trait ValueAnalysis<'tcx> {
                 // These terminators have no effect on the analysis.
             }
         }
+        terminator.edges()
     }
 
     fn handle_call_return(
@@ -291,19 +301,22 @@ pub trait ValueAnalysis<'tcx> {
         })
     }
 
-    fn handle_switch_int(
+    fn handle_switch_int<'mir>(
         &self,
-        discr: &Operand<'tcx>,
-        apply_edge_effects: &mut impl SwitchIntEdgeEffects<State<Self::Value>>,
-    ) {
-        self.super_switch_int(discr, apply_edge_effects)
+        discr: &'mir Operand<'tcx>,
+        targets: &'mir SwitchTargets,
+        state: &mut State<Self::Value>,
+    ) -> TerminatorEdges<'mir, 'tcx> {
+        self.super_switch_int(discr, targets, state)
     }
 
-    fn super_switch_int(
+    fn super_switch_int<'mir>(
         &self,
-        _discr: &Operand<'tcx>,
-        _apply_edge_effects: &mut impl SwitchIntEdgeEffects<State<Self::Value>>,
-    ) {
+        discr: &'mir Operand<'tcx>,
+        targets: &'mir SwitchTargets,
+        _state: &mut State<Self::Value>,
+    ) -> TerminatorEdges<'mir, 'tcx> {
+        TerminatorEdges::SwitchInt { discr, targets }
     }
 
     fn wrap(self) -> ValueAnalysisWrapper<Self>
@@ -353,14 +366,16 @@ where
         }
     }
 
-    fn apply_terminator_effect(
+    fn apply_terminator_effect<'mir>(
         &mut self,
         state: &mut Self::Domain,
-        terminator: &Terminator<'tcx>,
+        terminator: &'mir Terminator<'tcx>,
         _location: Location,
-    ) {
+    ) -> TerminatorEdges<'mir, 'tcx> {
         if state.is_reachable() {
-            self.0.handle_terminator(terminator, state);
+            self.0.handle_terminator(terminator, state)
+        } else {
+            TerminatorEdges::None
         }
     }
 
@@ -368,7 +383,7 @@ where
         &mut self,
         state: &mut Self::Domain,
         _block: BasicBlock,
-        return_places: crate::CallReturnPlaces<'_, 'tcx>,
+        return_places: CallReturnPlaces<'_, 'tcx>,
     ) {
         if state.is_reachable() {
             self.0.handle_call_return(return_places, state)
@@ -378,11 +393,9 @@ where
     fn apply_switch_int_edge_effects(
         &mut self,
         _block: BasicBlock,
-        discr: &Operand<'tcx>,
-        apply_edge_effects: &mut impl SwitchIntEdgeEffects<Self::Domain>,
+        _discr: &Operand<'tcx>,
+        _apply_edge_effects: &mut impl SwitchIntEdgeEffects<Self::Domain>,
     ) {
-        // FIXME: Dataflow framework provides no access to current state here.
-        self.0.handle_switch_int(discr, apply_edge_effects)
     }
 }
 
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index 58e9786ec1a..e72db1a59a0 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -57,8 +57,8 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
             | TerminatorKind::Yield { .. }
             | TerminatorKind::Assert { .. }
             | TerminatorKind::GeneratorDrop
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | 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 7529ed8186b..a793b384d81 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -180,6 +180,10 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
         throw_machine_stop_str!("calling functions isn't supported in ConstProp")
     }
 
+    fn panic_nounwind(_ecx: &mut InterpCx<'mir, 'tcx, Self>, _msg: &str) -> InterpResult<'tcx> {
+        throw_machine_stop_str!("panicking isn't supported in ConstProp")
+    }
+
     fn find_mir_or_eval_fn(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _instance: ty::Instance<'tcx>,
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index ac07c25763b..4f8ca916d5b 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -678,8 +678,8 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
             }
             // None of these have Operands to const-propagate.
             TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::Drop { .. }
diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs
index d1f2f0c76c8..3d442e5dca9 100644
--- a/compiler/rustc_mir_transform/src/coverage/counters.rs
+++ b/compiler/rustc_mir_transform/src/coverage/counters.rs
@@ -14,36 +14,76 @@ use rustc_index::bit_set::BitSet;
 use rustc_index::IndexVec;
 use rustc_middle::mir::coverage::*;
 
+use std::fmt::{self, Debug};
+
+/// The coverage counter or counter expression associated with a particular
+/// BCB node or BCB edge.
+#[derive(Clone)]
+pub(super) enum BcbCounter {
+    Counter { id: CounterId },
+    Expression { id: ExpressionId, lhs: Operand, op: Op, rhs: Operand },
+}
+
+impl BcbCounter {
+    fn is_expression(&self) -> bool {
+        matches!(self, Self::Expression { .. })
+    }
+
+    pub(super) fn as_operand(&self) -> Operand {
+        match *self {
+            BcbCounter::Counter { id, .. } => Operand::Counter(id),
+            BcbCounter::Expression { id, .. } => Operand::Expression(id),
+        }
+    }
+}
+
+impl Debug for BcbCounter {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::Counter { id, .. } => write!(fmt, "Counter({:?})", id.index()),
+            Self::Expression { id, lhs, op, rhs } => write!(
+                fmt,
+                "Expression({:?}) = {:?} {} {:?}",
+                id.index(),
+                lhs,
+                match op {
+                    Op::Add => "+",
+                    Op::Subtract => "-",
+                },
+                rhs,
+            ),
+        }
+    }
+}
+
 /// Generates and stores coverage counter and coverage expression information
 /// associated with nodes/edges in the BCB graph.
 pub(super) struct CoverageCounters {
-    function_source_hash: u64,
     next_counter_id: CounterId,
     next_expression_id: ExpressionId,
 
     /// Coverage counters/expressions that are associated with individual BCBs.
-    bcb_counters: IndexVec<BasicCoverageBlock, Option<CoverageKind>>,
+    bcb_counters: IndexVec<BasicCoverageBlock, Option<BcbCounter>>,
     /// Coverage counters/expressions that are associated with the control-flow
     /// edge between two BCBs.
-    bcb_edge_counters: FxHashMap<(BasicCoverageBlock, BasicCoverageBlock), CoverageKind>,
+    bcb_edge_counters: FxHashMap<(BasicCoverageBlock, BasicCoverageBlock), BcbCounter>,
     /// Tracks which BCBs have a counter associated with some incoming edge.
     /// Only used by debug assertions, to verify that BCBs with incoming edge
     /// counters do not have their own physical counters (expressions are allowed).
     bcb_has_incoming_edge_counters: BitSet<BasicCoverageBlock>,
     /// Expression nodes that are not directly associated with any particular
     /// BCB/edge, but are needed as operands to more complex expressions.
-    /// These are always `CoverageKind::Expression`.
-    pub(super) intermediate_expressions: Vec<CoverageKind>,
+    /// These are always [`BcbCounter::Expression`].
+    pub(super) intermediate_expressions: Vec<BcbCounter>,
 
     pub debug_counters: DebugCounters,
 }
 
 impl CoverageCounters {
-    pub(super) fn new(function_source_hash: u64, basic_coverage_blocks: &CoverageGraph) -> Self {
+    pub(super) fn new(basic_coverage_blocks: &CoverageGraph) -> Self {
         let num_bcbs = basic_coverage_blocks.num_nodes();
 
         Self {
-            function_source_hash,
             next_counter_id: CounterId::START,
             next_expression_id: ExpressionId::START,
 
@@ -57,12 +97,12 @@ impl CoverageCounters {
     }
 
     /// Activate the `DebugCounters` data structures, to provide additional debug formatting
-    /// features when formatting `CoverageKind` (counter) values.
+    /// features when formatting [`BcbCounter`] (counter) values.
     pub fn enable_debug(&mut self) {
         self.debug_counters.enable();
     }
 
-    /// Makes `CoverageKind` `Counter`s and `Expressions` for the `BasicCoverageBlock`s directly or
+    /// Makes [`BcbCounter`] `Counter`s and `Expressions` for the `BasicCoverageBlock`s directly or
     /// indirectly associated with `CoverageSpans`, and accumulates additional `Expression`s
     /// representing intermediate values.
     pub fn make_bcb_counters(
@@ -73,14 +113,11 @@ impl CoverageCounters {
         MakeBcbCounters::new(self, basic_coverage_blocks).make_bcb_counters(coverage_spans)
     }
 
-    fn make_counter<F>(&mut self, debug_block_label_fn: F) -> CoverageKind
+    fn make_counter<F>(&mut self, debug_block_label_fn: F) -> BcbCounter
     where
         F: Fn() -> Option<String>,
     {
-        let counter = CoverageKind::Counter {
-            function_source_hash: self.function_source_hash,
-            id: self.next_counter(),
-        };
+        let counter = BcbCounter::Counter { id: self.next_counter() };
         if self.debug_counters.is_enabled() {
             self.debug_counters.add_counter(&counter, (debug_block_label_fn)());
         }
@@ -93,19 +130,19 @@ impl CoverageCounters {
         op: Op,
         rhs: Operand,
         debug_block_label_fn: F,
-    ) -> CoverageKind
+    ) -> BcbCounter
     where
         F: Fn() -> Option<String>,
     {
         let id = self.next_expression();
-        let expression = CoverageKind::Expression { id, lhs, op, rhs };
+        let expression = BcbCounter::Expression { id, lhs, op, rhs };
         if self.debug_counters.is_enabled() {
             self.debug_counters.add_counter(&expression, (debug_block_label_fn)());
         }
         expression
     }
 
-    pub fn make_identity_counter(&mut self, counter_operand: Operand) -> CoverageKind {
+    pub fn make_identity_counter(&mut self, counter_operand: Operand) -> BcbCounter {
         let some_debug_block_label = if self.debug_counters.is_enabled() {
             self.debug_counters.some_block_label(counter_operand).cloned()
         } else {
@@ -134,7 +171,7 @@ impl CoverageCounters {
     fn set_bcb_counter(
         &mut self,
         bcb: BasicCoverageBlock,
-        counter_kind: CoverageKind,
+        counter_kind: BcbCounter,
     ) -> Result<Operand, Error> {
         debug_assert!(
             // If the BCB has an edge counter (to be injected into a new `BasicBlock`), it can also
@@ -158,7 +195,7 @@ impl CoverageCounters {
         &mut self,
         from_bcb: BasicCoverageBlock,
         to_bcb: BasicCoverageBlock,
-        counter_kind: CoverageKind,
+        counter_kind: BcbCounter,
     ) -> Result<Operand, Error> {
         if level_enabled!(tracing::Level::DEBUG) {
             // If the BCB has an edge counter (to be injected into a new `BasicBlock`), it can also
@@ -183,17 +220,17 @@ impl CoverageCounters {
         }
     }
 
-    pub(super) fn bcb_counter(&self, bcb: BasicCoverageBlock) -> Option<&CoverageKind> {
+    pub(super) fn bcb_counter(&self, bcb: BasicCoverageBlock) -> Option<&BcbCounter> {
         self.bcb_counters[bcb].as_ref()
     }
 
-    pub(super) fn take_bcb_counter(&mut self, bcb: BasicCoverageBlock) -> Option<CoverageKind> {
+    pub(super) fn take_bcb_counter(&mut self, bcb: BasicCoverageBlock) -> Option<BcbCounter> {
         self.bcb_counters[bcb].take()
     }
 
     pub(super) fn drain_bcb_counters(
         &mut self,
-    ) -> impl Iterator<Item = (BasicCoverageBlock, CoverageKind)> + '_ {
+    ) -> impl Iterator<Item = (BasicCoverageBlock, BcbCounter)> + '_ {
         self.bcb_counters
             .iter_enumerated_mut()
             .filter_map(|(bcb, counter)| Some((bcb, counter.take()?)))
@@ -201,7 +238,7 @@ impl CoverageCounters {
 
     pub(super) fn drain_bcb_edge_counters(
         &mut self,
-    ) -> impl Iterator<Item = ((BasicCoverageBlock, BasicCoverageBlock), CoverageKind)> + '_ {
+    ) -> impl Iterator<Item = ((BasicCoverageBlock, BasicCoverageBlock), BcbCounter)> + '_ {
         self.bcb_edge_counters.drain()
     }
 }
@@ -653,7 +690,7 @@ impl<'a> MakeBcbCounters<'a> {
         self.branch_counter(branch).is_none()
     }
 
-    fn branch_counter(&self, branch: &BcbBranch) -> Option<&CoverageKind> {
+    fn branch_counter(&self, branch: &BcbBranch) -> Option<&BcbCounter> {
         let to_bcb = branch.target_bcb;
         if let Some(from_bcb) = branch.edge_from_bcb {
             self.coverage_counters.bcb_edge_counters.get(&(from_bcb, to_bcb))
@@ -675,7 +712,7 @@ impl<'a> MakeBcbCounters<'a> {
     }
 
     #[inline]
-    fn format_counter(&self, counter_kind: &CoverageKind) -> String {
+    fn format_counter(&self, counter_kind: &BcbCounter) -> String {
         self.coverage_counters.debug_counters.format_counter(counter_kind)
     }
 }
diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs
index d2c0c4ba069..af616c498fd 100644
--- a/compiler/rustc_mir_transform/src/coverage/debug.rs
+++ b/compiler/rustc_mir_transform/src/coverage/debug.rs
@@ -108,7 +108,7 @@
 //!         recursively, generating labels with nested operations, enclosed in parentheses
 //!         (for example: `bcb2 + (bcb0 - bcb1)`).
 
-use super::counters::CoverageCounters;
+use super::counters::{BcbCounter, CoverageCounters};
 use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph};
 use super::spans::CoverageSpan;
 
@@ -199,9 +199,9 @@ impl DebugOptions {
 
 fn bool_option_val(option: &str, some_strval: Option<&str>) -> bool {
     if let Some(val) = some_strval {
-        if vec!["yes", "y", "on", "true"].contains(&val) {
+        if ["yes", "y", "on", "true"].contains(&val) {
             true
-        } else if vec!["no", "n", "off", "false"].contains(&val) {
+        } else if ["no", "n", "off", "false"].contains(&val) {
             false
         } else {
             bug!(
@@ -247,11 +247,11 @@ impl Default for ExpressionFormat {
     }
 }
 
-/// If enabled, this struct maintains a map from `CoverageKind` IDs (as `Operand`) to
-/// the `CoverageKind` data and optional label (normally, the counter's associated
+/// If enabled, this struct maintains a map from `BcbCounter` IDs (as `Operand`) to
+/// the `BcbCounter` data and optional label (normally, the counter's associated
 /// `BasicCoverageBlock` format string, if any).
 ///
-/// Use `format_counter` to convert one of these `CoverageKind` counters to a debug output string,
+/// Use `format_counter` to convert one of these `BcbCounter` counters to a debug output string,
 /// as directed by the `DebugOptions`. This allows the format of counter labels in logs and dump
 /// files (including the `CoverageGraph` graphviz file) to be changed at runtime, via environment
 /// variable.
@@ -276,7 +276,7 @@ impl DebugCounters {
         self.some_counters.is_some()
     }
 
-    pub fn add_counter(&mut self, counter_kind: &CoverageKind, some_block_label: Option<String>) {
+    pub fn add_counter(&mut self, counter_kind: &BcbCounter, some_block_label: Option<String>) {
         if let Some(counters) = &mut self.some_counters {
             let id = counter_kind.as_operand();
             counters
@@ -291,21 +291,20 @@ impl DebugCounters {
         })
     }
 
-    pub fn format_counter(&self, counter_kind: &CoverageKind) -> String {
+    pub fn format_counter(&self, counter_kind: &BcbCounter) -> String {
         match *counter_kind {
-            CoverageKind::Counter { .. } => {
+            BcbCounter::Counter { .. } => {
                 format!("Counter({})", self.format_counter_kind(counter_kind))
             }
-            CoverageKind::Expression { .. } => {
+            BcbCounter::Expression { .. } => {
                 format!("Expression({})", self.format_counter_kind(counter_kind))
             }
-            CoverageKind::Unreachable { .. } => "Unreachable".to_owned(),
         }
     }
 
-    fn format_counter_kind(&self, counter_kind: &CoverageKind) -> String {
+    fn format_counter_kind(&self, counter_kind: &BcbCounter) -> String {
         let counter_format = &debug_options().counter_format;
-        if let CoverageKind::Expression { id, lhs, op, rhs } = *counter_kind {
+        if let BcbCounter::Expression { id, lhs, op, rhs } = *counter_kind {
             if counter_format.operation {
                 return format!(
                     "{}{} {} {}",
@@ -346,7 +345,7 @@ impl DebugCounters {
         }
         if let Some(counters) = &self.some_counters {
             if let Some(DebugCounter { counter_kind, some_block_label }) = counters.get(&operand) {
-                if let CoverageKind::Expression { .. } = counter_kind {
+                if let BcbCounter::Expression { .. } = counter_kind {
                     if let Some(label) = some_block_label && debug_options().counter_format.block {
                         return format!(
                             "{}:({})",
@@ -366,12 +365,12 @@ impl DebugCounters {
 /// A non-public support class to `DebugCounters`.
 #[derive(Debug)]
 struct DebugCounter {
-    counter_kind: CoverageKind,
+    counter_kind: BcbCounter,
     some_block_label: Option<String>,
 }
 
 impl DebugCounter {
-    fn new(counter_kind: CoverageKind, some_block_label: Option<String>) -> Self {
+    fn new(counter_kind: BcbCounter, some_block_label: Option<String>) -> Self {
         Self { counter_kind, some_block_label }
     }
 }
@@ -380,9 +379,9 @@ impl DebugCounter {
 /// a Graphviz (.dot file) representation of the `CoverageGraph`, for debugging purposes.
 pub(super) struct GraphvizData {
     some_bcb_to_coverage_spans_with_counters:
-        Option<FxHashMap<BasicCoverageBlock, Vec<(CoverageSpan, CoverageKind)>>>,
-    some_bcb_to_dependency_counters: Option<FxHashMap<BasicCoverageBlock, Vec<CoverageKind>>>,
-    some_edge_to_counter: Option<FxHashMap<(BasicCoverageBlock, BasicBlock), CoverageKind>>,
+        Option<FxHashMap<BasicCoverageBlock, Vec<(CoverageSpan, BcbCounter)>>>,
+    some_bcb_to_dependency_counters: Option<FxHashMap<BasicCoverageBlock, Vec<BcbCounter>>>,
+    some_edge_to_counter: Option<FxHashMap<(BasicCoverageBlock, BasicBlock), BcbCounter>>,
 }
 
 impl GraphvizData {
@@ -409,7 +408,7 @@ impl GraphvizData {
         &mut self,
         bcb: BasicCoverageBlock,
         coverage_span: &CoverageSpan,
-        counter_kind: &CoverageKind,
+        counter_kind: &BcbCounter,
     ) {
         if let Some(bcb_to_coverage_spans_with_counters) =
             self.some_bcb_to_coverage_spans_with_counters.as_mut()
@@ -424,7 +423,7 @@ impl GraphvizData {
     pub fn get_bcb_coverage_spans_with_counters(
         &self,
         bcb: BasicCoverageBlock,
-    ) -> Option<&[(CoverageSpan, CoverageKind)]> {
+    ) -> Option<&[(CoverageSpan, BcbCounter)]> {
         if let Some(bcb_to_coverage_spans_with_counters) =
             self.some_bcb_to_coverage_spans_with_counters.as_ref()
         {
@@ -437,7 +436,7 @@ impl GraphvizData {
     pub fn add_bcb_dependency_counter(
         &mut self,
         bcb: BasicCoverageBlock,
-        counter_kind: &CoverageKind,
+        counter_kind: &BcbCounter,
     ) {
         if let Some(bcb_to_dependency_counters) = self.some_bcb_to_dependency_counters.as_mut() {
             bcb_to_dependency_counters
@@ -447,7 +446,7 @@ impl GraphvizData {
         }
     }
 
-    pub fn get_bcb_dependency_counters(&self, bcb: BasicCoverageBlock) -> Option<&[CoverageKind]> {
+    pub fn get_bcb_dependency_counters(&self, bcb: BasicCoverageBlock) -> Option<&[BcbCounter]> {
         if let Some(bcb_to_dependency_counters) = self.some_bcb_to_dependency_counters.as_ref() {
             bcb_to_dependency_counters.get(&bcb).map(Deref::deref)
         } else {
@@ -459,7 +458,7 @@ impl GraphvizData {
         &mut self,
         from_bcb: BasicCoverageBlock,
         to_bb: BasicBlock,
-        counter_kind: &CoverageKind,
+        counter_kind: &BcbCounter,
     ) {
         if let Some(edge_to_counter) = self.some_edge_to_counter.as_mut() {
             edge_to_counter
@@ -472,7 +471,7 @@ impl GraphvizData {
         &self,
         from_bcb: BasicCoverageBlock,
         to_bb: BasicBlock,
-    ) -> Option<&CoverageKind> {
+    ) -> Option<&BcbCounter> {
         if let Some(edge_to_counter) = self.some_edge_to_counter.as_ref() {
             edge_to_counter.get(&(from_bcb, to_bb))
         } else {
@@ -488,7 +487,7 @@ impl GraphvizData {
 pub(super) struct UsedExpressions {
     some_used_expression_operands: Option<FxHashMap<Operand, Vec<ExpressionId>>>,
     some_unused_expressions:
-        Option<Vec<(CoverageKind, Option<BasicCoverageBlock>, BasicCoverageBlock)>>,
+        Option<Vec<(BcbCounter, Option<BasicCoverageBlock>, BasicCoverageBlock)>>,
 }
 
 impl UsedExpressions {
@@ -506,16 +505,16 @@ impl UsedExpressions {
         self.some_used_expression_operands.is_some()
     }
 
-    pub fn add_expression_operands(&mut self, expression: &CoverageKind) {
+    pub fn add_expression_operands(&mut self, expression: &BcbCounter) {
         if let Some(used_expression_operands) = self.some_used_expression_operands.as_mut() {
-            if let CoverageKind::Expression { id, lhs, rhs, .. } = *expression {
+            if let BcbCounter::Expression { id, lhs, rhs, .. } = *expression {
                 used_expression_operands.entry(lhs).or_insert_with(Vec::new).push(id);
                 used_expression_operands.entry(rhs).or_insert_with(Vec::new).push(id);
             }
         }
     }
 
-    pub fn expression_is_used(&self, expression: &CoverageKind) -> bool {
+    pub fn expression_is_used(&self, expression: &BcbCounter) -> bool {
         if let Some(used_expression_operands) = self.some_used_expression_operands.as_ref() {
             used_expression_operands.contains_key(&expression.as_operand())
         } else {
@@ -525,7 +524,7 @@ impl UsedExpressions {
 
     pub fn add_unused_expression_if_not_found(
         &mut self,
-        expression: &CoverageKind,
+        expression: &BcbCounter,
         edge_from_bcb: Option<BasicCoverageBlock>,
         target_bcb: BasicCoverageBlock,
     ) {
@@ -540,11 +539,11 @@ impl UsedExpressions {
         }
     }
 
-    /// Return the list of unused counters (if any) as a tuple with the counter (`CoverageKind`),
+    /// Return the list of unused counters (if any) as a tuple with the counter (`BcbCounter`),
     /// optional `from_bcb` (if it was an edge counter), and `target_bcb`.
     pub fn get_unused_expressions(
         &self,
-    ) -> Vec<(CoverageKind, Option<BasicCoverageBlock>, BasicCoverageBlock)> {
+    ) -> Vec<(BcbCounter, Option<BasicCoverageBlock>, BasicCoverageBlock)> {
         if let Some(unused_expressions) = self.some_unused_expressions.as_ref() {
             unused_expressions.clone()
         } else {
@@ -560,7 +559,7 @@ impl UsedExpressions {
         bcb_counters_without_direct_coverage_spans: &[(
             Option<BasicCoverageBlock>,
             BasicCoverageBlock,
-            CoverageKind,
+            BcbCounter,
         )],
     ) {
         if self.is_enabled() {
@@ -662,7 +661,7 @@ pub(super) fn dump_coverage_graphviz<'tcx>(
     basic_coverage_blocks: &CoverageGraph,
     coverage_counters: &CoverageCounters,
     graphviz_data: &GraphvizData,
-    intermediate_expressions: &[CoverageKind],
+    intermediate_expressions: &[BcbCounter],
     debug_used_expressions: &UsedExpressions,
 ) {
     let debug_counters = &coverage_counters.debug_counters;
@@ -743,9 +742,9 @@ fn bcb_to_string_sections<'tcx>(
     coverage_counters: &CoverageCounters,
     bcb: BasicCoverageBlock,
     bcb_data: &BasicCoverageBlockData,
-    some_coverage_spans_with_counters: Option<&[(CoverageSpan, CoverageKind)]>,
-    some_dependency_counters: Option<&[CoverageKind]>,
-    some_intermediate_expressions: Option<&[CoverageKind]>,
+    some_coverage_spans_with_counters: Option<&[(CoverageSpan, BcbCounter)]>,
+    some_dependency_counters: Option<&[BcbCounter]>,
+    some_intermediate_expressions: Option<&[BcbCounter]>,
 ) -> Vec<String> {
     let debug_counters = &coverage_counters.debug_counters;
 
diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs
index 59b01ffec0f..d3d4fcd3a52 100644
--- a/compiler/rustc_mir_transform/src/coverage/graph.rs
+++ b/compiler/rustc_mir_transform/src/coverage/graph.rs
@@ -116,7 +116,7 @@ impl CoverageGraph {
 
             match term.kind {
                 TerminatorKind::Return { .. }
-                | TerminatorKind::Terminate
+                | TerminatorKind::UnwindTerminate
                 | TerminatorKind::Yield { .. }
                 | TerminatorKind::SwitchInt { .. } => {
                     // The `bb` has more than one _outgoing_ edge, or exits the function. Save the
@@ -146,7 +146,7 @@ impl CoverageGraph {
                 // is as intended. (See Issue #78544 for a possible future option to support
                 // coverage in test programs that panic.)
                 TerminatorKind::Goto { .. }
-                | TerminatorKind::Resume
+                | TerminatorKind::UnwindResume
                 | TerminatorKind::Unreachable
                 | TerminatorKind::Drop { .. }
                 | TerminatorKind::Call { .. }
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index e08b6d6f6e8..8c9eae508b4 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -8,9 +8,9 @@ mod spans;
 #[cfg(test)]
 mod tests;
 
-use counters::CoverageCounters;
-use graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph};
-use spans::{CoverageSpan, CoverageSpans};
+use self::counters::{BcbCounter, CoverageCounters};
+use self::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph};
+use self::spans::{CoverageSpan, CoverageSpans};
 
 use crate::MirPass;
 
@@ -106,6 +106,7 @@ struct Instrumentor<'a, 'tcx> {
     source_file: Lrc<SourceFile>,
     fn_sig_span: Span,
     body_span: Span,
+    function_source_hash: u64,
     basic_coverage_blocks: CoverageGraph,
     coverage_counters: CoverageCounters,
 }
@@ -137,7 +138,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
 
         let function_source_hash = hash_mir_source(tcx, hir_body);
         let basic_coverage_blocks = CoverageGraph::from_mir(mir_body);
-        let coverage_counters = CoverageCounters::new(function_source_hash, &basic_coverage_blocks);
+        let coverage_counters = CoverageCounters::new(&basic_coverage_blocks);
 
         Self {
             pass_name,
@@ -146,6 +147,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
             source_file,
             fn_sig_span,
             body_span,
+            function_source_hash,
             basic_coverage_blocks,
             coverage_counters,
         }
@@ -270,8 +272,11 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
 
         ////////////////////////////////////////////////////
         // Finally, inject the intermediate expressions collected along the way.
-        for intermediate_expression in self.coverage_counters.intermediate_expressions.drain(..) {
-            inject_intermediate_expression(self.mir_body, intermediate_expression);
+        for intermediate_expression in &self.coverage_counters.intermediate_expressions {
+            inject_intermediate_expression(
+                self.mir_body,
+                self.make_mir_coverage_kind(intermediate_expression),
+            );
         }
     }
 
@@ -309,19 +314,14 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
             };
             graphviz_data.add_bcb_coverage_span_with_counter(bcb, &covspan, &counter_kind);
 
-            debug!(
-                "Calling make_code_region(file_name={}, source_file={:?}, span={}, body_span={})",
-                file_name,
-                self.source_file,
-                source_map.span_to_diagnostic_string(span),
-                source_map.span_to_diagnostic_string(body_span)
-            );
+            let code_region =
+                make_code_region(source_map, file_name, &self.source_file, span, body_span);
 
             inject_statement(
                 self.mir_body,
-                counter_kind,
+                self.make_mir_coverage_kind(&counter_kind),
                 self.bcb_leader_bb(bcb),
-                Some(make_code_region(source_map, file_name, &self.source_file, span, body_span)),
+                Some(code_region),
             );
         }
     }
@@ -367,7 +367,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
             );
 
             match counter_kind {
-                CoverageKind::Counter { .. } => {
+                BcbCounter::Counter { .. } => {
                     let inject_to_bb = if let Some(from_bcb) = edge_from_bcb {
                         // The MIR edge starts `from_bb` (the outgoing / last BasicBlock in
                         // `from_bcb`) and ends at `to_bb` (the incoming / first BasicBlock in the
@@ -400,12 +400,17 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
                         target_bb
                     };
 
-                    inject_statement(self.mir_body, counter_kind, inject_to_bb, None);
+                    inject_statement(
+                        self.mir_body,
+                        self.make_mir_coverage_kind(&counter_kind),
+                        inject_to_bb,
+                        None,
+                    );
                 }
-                CoverageKind::Expression { .. } => {
-                    inject_intermediate_expression(self.mir_body, counter_kind)
-                }
-                _ => bug!("CoverageKind should be a counter"),
+                BcbCounter::Expression { .. } => inject_intermediate_expression(
+                    self.mir_body,
+                    self.make_mir_coverage_kind(&counter_kind),
+                ),
             }
         }
     }
@@ -426,9 +431,20 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
     }
 
     #[inline]
-    fn format_counter(&self, counter_kind: &CoverageKind) -> String {
+    fn format_counter(&self, counter_kind: &BcbCounter) -> String {
         self.coverage_counters.debug_counters.format_counter(counter_kind)
     }
+
+    fn make_mir_coverage_kind(&self, counter_kind: &BcbCounter) -> CoverageKind {
+        match *counter_kind {
+            BcbCounter::Counter { id } => {
+                CoverageKind::Counter { function_source_hash: self.function_source_hash, id }
+            }
+            BcbCounter::Expression { id, lhs, op, rhs } => {
+                CoverageKind::Expression { id, lhs, op, rhs }
+            }
+        }
+    }
 }
 
 fn inject_edge_counter_basic_block(
@@ -498,6 +514,14 @@ fn make_code_region(
     span: Span,
     body_span: Span,
 ) -> CodeRegion {
+    debug!(
+        "Called make_code_region(file_name={}, source_file={:?}, span={}, body_span={})",
+        file_name,
+        source_file,
+        source_map.span_to_diagnostic_string(span),
+        source_map.span_to_diagnostic_string(body_span)
+    );
+
     let (start_line, mut start_col) = source_file.lookup_file_pos(span.lo());
     let (end_line, end_col) = if span.hi() == span.lo() {
         let (end_line, mut end_col) = (start_line, start_col);
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index deebf5345ba..6fabaca524a 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -867,8 +867,8 @@ pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Sp
         }
 
         // Retain spans from all other terminators
-        TerminatorKind::Resume
-        | TerminatorKind::Terminate
+        TerminatorKind::UnwindResume
+        | TerminatorKind::UnwindTerminate
         | 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 d797a6057a7..4a066ed3abd 100644
--- a/compiler/rustc_mir_transform/src/coverage/tests.rs
+++ b/compiler/rustc_mir_transform/src/coverage/tests.rs
@@ -34,7 +34,6 @@ use itertools::Itertools;
 use rustc_data_structures::graph::WithNumNodes;
 use rustc_data_structures::graph::WithSuccessors;
 use rustc_index::{Idx, IndexVec};
-use rustc_middle::mir::coverage::CoverageKind;
 use rustc_middle::mir::*;
 use rustc_middle::ty;
 use rustc_span::{self, BytePos, Pos, Span, DUMMY_SP};
@@ -675,8 +674,8 @@ fn test_make_bcb_counters() {
                 ));
             }
         }
-        let mut coverage_counters = counters::CoverageCounters::new(0, &basic_coverage_blocks);
-        let () = coverage_counters
+        let mut coverage_counters = counters::CoverageCounters::new(&basic_coverage_blocks);
+        coverage_counters
             .make_bcb_counters(&mut basic_coverage_blocks, &coverage_spans)
             .expect("should be Ok");
         assert_eq!(coverage_counters.intermediate_expressions.len(), 0);
@@ -685,7 +684,7 @@ fn test_make_bcb_counters() {
         assert_eq!(
             0, // bcb1 has a `Counter` with id = 0
             match coverage_counters.bcb_counter(bcb1).expect("should have a counter") {
-                CoverageKind::Counter { id, .. } => id,
+                counters::BcbCounter::Counter { id, .. } => id,
                 _ => panic!("expected a Counter"),
             }
             .as_u32()
@@ -695,7 +694,7 @@ fn test_make_bcb_counters() {
         assert_eq!(
             1, // bcb2 has a `Counter` with id = 1
             match coverage_counters.bcb_counter(bcb2).expect("should have a counter") {
-                CoverageKind::Counter { id, .. } => id,
+                counters::BcbCounter::Counter { id, .. } => id,
                 _ => panic!("expected a Counter"),
             }
             .as_u32()
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index 7d7588fcaec..3a1ef3e7d64 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -13,9 +13,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_mir_dataflow::value_analysis::{
     Map, State, TrackElem, ValueAnalysis, ValueAnalysisWrapper, ValueOrPlace,
 };
-use rustc_mir_dataflow::{
-    lattice::FlatSet, Analysis, Results, ResultsVisitor, SwitchIntEdgeEffects,
-};
+use rustc_mir_dataflow::{lattice::FlatSet, Analysis, Results, ResultsVisitor};
 use rustc_span::DUMMY_SP;
 use rustc_target::abi::{Align, FieldIdx, VariantIdx};
 
@@ -249,49 +247,27 @@ impl<'tcx> ValueAnalysis<'tcx> for ConstAnalysis<'_, 'tcx> {
             .unwrap_or(FlatSet::Top)
     }
 
-    fn handle_switch_int(
+    fn handle_switch_int<'mir>(
         &self,
-        discr: &Operand<'tcx>,
-        apply_edge_effects: &mut impl SwitchIntEdgeEffects<State<Self::Value>>,
-    ) {
-        // FIXME: The dataflow framework only provides the state if we call `apply()`, which makes
-        // this more inefficient than it has to be.
-        let mut discr_value = None;
-        let mut handled = false;
-        apply_edge_effects.apply(|state, target| {
-            let discr_value = match discr_value {
-                Some(value) => value,
-                None => {
-                    let value = match self.handle_operand(discr, state) {
-                        ValueOrPlace::Value(value) => value,
-                        ValueOrPlace::Place(place) => state.get_idx(place, self.map()),
-                    };
-                    let result = match value {
-                        FlatSet::Top => FlatSet::Top,
-                        FlatSet::Elem(ScalarTy(scalar, _)) => {
-                            let int = scalar.assert_int();
-                            FlatSet::Elem(int.assert_bits(int.size()))
-                        }
-                        FlatSet::Bottom => FlatSet::Bottom,
-                    };
-                    discr_value = Some(result);
-                    result
-                }
-            };
-
-            let FlatSet::Elem(choice) = discr_value else {
-                // Do nothing if we don't know which branch will be taken.
-                return;
-            };
-
-            if target.value.map(|n| n == choice).unwrap_or(!handled) {
-                // Branch is taken. Has no effect on state.
-                handled = true;
-            } else {
-                // Branch is not taken.
-                state.mark_unreachable();
+        discr: &'mir Operand<'tcx>,
+        targets: &'mir SwitchTargets,
+        state: &mut State<Self::Value>,
+    ) -> TerminatorEdges<'mir, 'tcx> {
+        let value = match self.handle_operand(discr, state) {
+            ValueOrPlace::Value(value) => value,
+            ValueOrPlace::Place(place) => state.get_idx(place, self.map()),
+        };
+        match value {
+            // We are branching on uninitialized data, this is UB, treat it as unreachable.
+            // This allows the set of visited edges to grow monotonically with the lattice.
+            FlatSet::Bottom => TerminatorEdges::None,
+            FlatSet::Elem(ScalarTy(scalar, _)) => {
+                let int = scalar.assert_int();
+                let choice = int.assert_bits(int.size());
+                TerminatorEdges::Single(targets.target_for_value(choice))
             }
-        })
+            FlatSet::Top => TerminatorEdges::SwitchInt { discr, targets },
+        }
     }
 }
 
@@ -565,6 +541,13 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm
         unimplemented!()
     }
 
+    fn panic_nounwind(
+        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        _msg: &str,
+    ) -> interpret::InterpResult<'tcx> {
+        unimplemented!()
+    }
+
     fn call_intrinsic(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _instance: ty::Instance<'tcx>,
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
index 60ca3dfb2da..79645310a39 100644
--- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
+++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -203,7 +203,12 @@ pub fn deduced_param_attrs<'tcx>(
         body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map(
             |(arg_index, local_decl)| DeducedParamAttrs {
                 read_only: !deduce_read_only.mutable_args.contains(arg_index)
-                    && local_decl.ty.is_freeze(tcx, param_env),
+                    // We must normalize here to reveal opaques and normalize
+                    // their substs, otherwise we'll see exponential blow-up in
+                    // compile times: #113372
+                    && tcx
+                        .normalize_erasing_regions(param_env, local_decl.ty)
+                        .is_freeze(tcx, param_env),
             },
         ),
     );
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index b73b72c3192..041f7c7221e 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -647,8 +647,8 @@ impl WriteInfo {
                 }
             }
             TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | 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 43757a9ea35..a80ae480089 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -48,6 +48,7 @@ use std::fmt;
 pub struct ElaborateDrops;
 
 impl<'tcx> MirPass<'tcx> for ElaborateDrops {
+    #[instrument(level = "trace", skip(self, tcx, body))]
     fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
         debug!("elaborate_drops({:?} @ {:?})", body.source, body.span);
 
@@ -65,23 +66,23 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
         };
         let elaborate_patch = {
             let env = MoveDataParamEnv { move_data, param_env };
-            remove_dead_unwinds(tcx, body, &env);
 
-            let inits = MaybeInitializedPlaces::new(tcx, body, &env)
+            let mut inits = MaybeInitializedPlaces::new(tcx, body, &env)
+                .skipping_unreachable_unwind()
                 .into_engine(tcx, body)
                 .pass_name("elaborate_drops")
                 .iterate_to_fixpoint()
                 .into_results_cursor(body);
+            let dead_unwinds = compute_dead_unwinds(&body, &mut inits);
 
             let uninits = MaybeUninitializedPlaces::new(tcx, body, &env)
                 .mark_inactive_variants_as_uninit()
+                .skipping_unreachable_unwind(dead_unwinds)
                 .into_engine(tcx, body)
                 .pass_name("elaborate_drops")
                 .iterate_to_fixpoint()
                 .into_results_cursor(body);
 
-            let reachable = traversal::reachable_as_bitset(body);
-
             let drop_flags = IndexVec::from_elem(None, &env.move_data.move_paths);
             ElaborateDropsCtxt {
                 tcx,
@@ -90,7 +91,6 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
                 init_data: InitializationData { inits, uninits },
                 drop_flags,
                 patch: MirPatch::new(body),
-                reachable,
             }
             .elaborate()
         };
@@ -99,65 +99,30 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops {
     }
 }
 
-/// Removes unwind edges which are known to be unreachable, because they are in `drop` terminators
+/// Records unwind edges which are known to be unreachable, because they are in `drop` terminators
 /// that can't drop anything.
-fn remove_dead_unwinds<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    body: &mut Body<'tcx>,
-    env: &MoveDataParamEnv<'tcx>,
-) {
-    debug!("remove_dead_unwinds({:?})", body.span);
+#[instrument(level = "trace", skip(body, flow_inits), ret)]
+fn compute_dead_unwinds<'mir, 'tcx>(
+    body: &'mir Body<'tcx>,
+    flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
+) -> BitSet<BasicBlock> {
     // We only need to do this pass once, because unwind edges can only
     // reach cleanup blocks, which can't have unwind edges themselves.
-    let mut dead_unwinds = Vec::new();
-    let mut flow_inits = MaybeInitializedPlaces::new(tcx, body, &env)
-        .into_engine(tcx, body)
-        .pass_name("remove_dead_unwinds")
-        .iterate_to_fixpoint()
-        .into_results_cursor(body);
+    let mut dead_unwinds = BitSet::new_empty(body.basic_blocks.len());
     for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
-        let place = match bb_data.terminator().kind {
-            TerminatorKind::Drop { place, unwind: UnwindAction::Cleanup(_), .. } => place,
-            _ => continue,
-        };
-
-        debug!("remove_dead_unwinds @ {:?}: {:?}", bb, bb_data);
-
-        let LookupResult::Exact(path) = env.move_data.rev_lookup.find(place.as_ref()) else {
-            debug!("remove_dead_unwinds: has parent; skipping");
+        let TerminatorKind::Drop { place, unwind: UnwindAction::Cleanup(_), .. } =
+            bb_data.terminator().kind
+        else {
             continue;
         };
 
         flow_inits.seek_before_primary_effect(body.terminator_loc(bb));
-        debug!(
-            "remove_dead_unwinds @ {:?}: path({:?})={:?}; init_data={:?}",
-            bb,
-            place,
-            path,
-            flow_inits.get()
-        );
-
-        let mut maybe_live = false;
-        on_all_drop_children_bits(tcx, body, &env, path, |child| {
-            maybe_live |= flow_inits.contains(child);
-        });
-
-        debug!("remove_dead_unwinds @ {:?}: maybe_live={}", bb, maybe_live);
-        if !maybe_live {
-            dead_unwinds.push(bb);
+        if flow_inits.analysis().is_unwind_dead(place, flow_inits.get()) {
+            dead_unwinds.insert(bb);
         }
     }
 
-    if dead_unwinds.is_empty() {
-        return;
-    }
-
-    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 = UnwindAction::Unreachable;
-        }
-    }
+    dead_unwinds
 }
 
 struct InitializationData<'mir, 'tcx> {
@@ -290,7 +255,6 @@ struct ElaborateDropsCtxt<'a, 'tcx> {
     init_data: InitializationData<'a, 'tcx>,
     drop_flags: IndexVec<MovePathIndex, Option<Local>>,
     patch: MirPatch<'tcx>,
-    reachable: BitSet<BasicBlock>,
 }
 
 impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
@@ -330,9 +294,6 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
 
     fn collect_drop_flags(&mut self) {
         for (bb, data) in self.body.basic_blocks.iter_enumerated() {
-            if !self.reachable.contains(bb) {
-                continue;
-            }
             let terminator = data.terminator();
             let place = match terminator.kind {
                 TerminatorKind::Drop { ref place, .. } => place,
@@ -384,9 +345,6 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
 
     fn elaborate_drops(&mut self) {
         for (bb, data) in self.body.basic_blocks.iter_enumerated() {
-            if !self.reachable.contains(bb) {
-                continue;
-            }
             let loc = Location { block: bb, statement_index: data.statements.len() };
             let terminator = data.terminator();
 
@@ -465,9 +423,6 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
 
     fn drop_flags_for_fn_rets(&mut self) {
         for (bb, data) in self.body.basic_blocks.iter_enumerated() {
-            if !self.reachable.contains(bb) {
-                continue;
-            }
             if let TerminatorKind::Call {
                 destination,
                 target: Some(tgt),
@@ -506,9 +461,6 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
         // clobbered before they are read.
 
         for (bb, data) in self.body.basic_blocks.iter_enumerated() {
-            if !self.reachable.contains(bb) {
-                continue;
-            }
             debug!("drop_flags_for_locs({:?})", data);
             for i in 0..(data.statements.len() + 1) {
                 debug!("drop_flag_for_locs: stmt {}", i);
@@ -518,7 +470,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                             // drop elaboration should handle that by itself
                             continue;
                         }
-                        TerminatorKind::Resume => {
+                        TerminatorKind::UnwindResume => {
                             // It is possible for `Resume` to be patched
                             // (in particular it can be patched to be replaced with
                             // a Goto; see `MirPatch::new`).
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 797a1a86846..96077322575 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -50,8 +50,10 @@
 //! For generators with state 1 (returned) and state 2 (poisoned) it does nothing.
 //! Otherwise it drops all the values in scope at the last suspension point.
 
+use crate::abort_unwinding_calls;
 use crate::deref_separator::deref_finder;
 use crate::errors;
+use crate::pass_manager as pm;
 use crate::simplify;
 use crate::MirPass;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -64,6 +66,7 @@ use rustc_index::{Idx, IndexVec};
 use rustc_middle::mir::dump_mir;
 use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::*;
+use rustc_middle::ty::InstanceDef;
 use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
 use rustc_middle::ty::{GeneratorArgs, GenericArgsRef};
 use rustc_mir_dataflow::impls::{
@@ -1147,7 +1150,25 @@ fn create_generator_drop_shim<'tcx>(
     // unrelated code from the resume part of the function
     simplify::remove_dead_blocks(tcx, &mut body);
 
+    // Update the body's def to become the drop glue.
+    // This needs to be updated before the AbortUnwindingCalls pass.
+    let gen_instance = body.source.instance;
+    let drop_in_place = tcx.require_lang_item(LangItem::DropInPlace, None);
+    let drop_instance = InstanceDef::DropGlue(drop_in_place, Some(gen_ty));
+    body.source.instance = drop_instance;
+
+    pm::run_passes_no_validate(
+        tcx,
+        &mut body,
+        &[&abort_unwinding_calls::AbortUnwindingCalls],
+        None,
+    );
+
+    // Temporary change MirSource to generator's instance so that dump_mir produces more sensible
+    // filename.
+    body.source.instance = gen_instance;
     dump_mir(tcx, false, "generator_drop", &0, &body, |_, _| Ok(()));
+    body.source.instance = drop_instance;
 
     body
 }
@@ -1218,7 +1239,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
             // These never unwind.
             TerminatorKind::Goto { .. }
             | TerminatorKind::SwitchInt { .. }
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::GeneratorDrop
@@ -1227,7 +1248,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
 
             // Resume will *continue* unwinding, but if there's no other unwinding terminator it
             // will never be reached.
-            TerminatorKind::Resume => {}
+            TerminatorKind::UnwindResume => {}
 
             TerminatorKind::Yield { .. } => {
                 unreachable!("`can_unwind` called before generator transform")
@@ -1258,14 +1279,14 @@ fn create_generator_resume_function<'tcx>(
         let source_info = SourceInfo::outermost(body.span);
         let poison_block = body.basic_blocks_mut().push(BasicBlockData {
             statements: vec![transform.set_discr(VariantIdx::new(POISONED), source_info)],
-            terminator: Some(Terminator { source_info, kind: TerminatorKind::Resume }),
+            terminator: Some(Terminator { source_info, kind: TerminatorKind::UnwindResume }),
             is_cleanup: true,
         });
 
         for (idx, block) in body.basic_blocks_mut().iter_enumerated_mut() {
             let source_info = block.terminator().source_info;
 
-            if let TerminatorKind::Resume = block.terminator().kind {
+            if let TerminatorKind::UnwindResume = block.terminator().kind {
                 // An existing `Resume` terminator is redirected to jump to our dedicated
                 // "poisoning block" above.
                 if idx != poison_block {
@@ -1317,6 +1338,8 @@ fn create_generator_resume_function<'tcx>(
     // unrelated code from the drop part of the function
     simplify::remove_dead_blocks(tcx, body);
 
+    pm::run_passes_no_validate(tcx, body, &[&abort_unwinding_calls::AbortUnwindingCalls], None);
+
     dump_mir(tcx, false, "generator_resume", &0, body, |_, _| Ok(()));
 }
 
@@ -1735,8 +1758,8 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
             TerminatorKind::Call { .. }
             | TerminatorKind::Goto { .. }
             | TerminatorKind::SwitchInt { .. }
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | 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 fc9e18378d5..734e93783d1 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -839,7 +839,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
                     self.cost += LANDINGPAD_PENALTY;
                 }
             }
-            TerminatorKind::Resume => self.cost += RESUME_PENALTY,
+            TerminatorKind::UnwindResume => self.cost += RESUME_PENALTY,
             TerminatorKind::InlineAsm { unwind, .. } => {
                 self.cost += INSTR_COST;
                 if let UnwindAction::Cleanup(_) = unwind {
@@ -1017,15 +1017,15 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
                     TerminatorKind::Unreachable
                 }
             }
-            TerminatorKind::Resume => {
+            TerminatorKind::UnwindResume => {
                 terminator.kind = match self.cleanup_block {
                     UnwindAction::Cleanup(tgt) => TerminatorKind::Goto { target: tgt },
-                    UnwindAction::Continue => TerminatorKind::Resume,
+                    UnwindAction::Continue => TerminatorKind::UnwindResume,
                     UnwindAction::Unreachable => TerminatorKind::Unreachable,
-                    UnwindAction::Terminate => TerminatorKind::Terminate,
+                    UnwindAction::Terminate => TerminatorKind::UnwindTerminate,
                 };
             }
-            TerminatorKind::Terminate => {}
+            TerminatorKind::UnwindTerminate => {}
             TerminatorKind::Unreachable => {}
             TerminatorKind::FalseEdge { ref mut real_target, ref mut imaginary_target } => {
                 *real_target = self.map_block(*real_target);
diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs
index c17c791f9c3..49a940b5779 100644
--- a/compiler/rustc_mir_transform/src/ref_prop.rs
+++ b/compiler/rustc_mir_transform/src/ref_prop.rs
@@ -265,7 +265,6 @@ fn compute_replacement<'tcx>(
         targets,
         storage_to_remove,
         allowed_replacements,
-        fully_replacable_locals,
         any_replacement: false,
     };
 
@@ -346,7 +345,6 @@ struct Replacer<'tcx> {
     storage_to_remove: BitSet<Local>,
     allowed_replacements: FxHashSet<(Local, Location)>,
     any_replacement: bool,
-    fully_replacable_locals: BitSet<Local>,
 }
 
 impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
@@ -366,12 +364,6 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
             if let Some((&PlaceElem::Deref, rest)) = target.projection.split_last() {
                 *place = Place::from(target.local).project_deeper(rest, self.tcx);
                 self.any_replacement = true;
-            } else if self.fully_replacable_locals.contains(place.local)
-                && let Some(references) = debuginfo.references.checked_add(1)
-            {
-                debuginfo.references = references;
-                *place = target;
-                self.any_replacement = true;
             } else {
                 break
             }
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 4941c9edce3..5782adbb3ff 100644
--- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
+++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
@@ -6,8 +6,8 @@ use rustc_middle::ty::TyCtxt;
 use rustc_target::spec::PanicStrategy;
 
 /// A pass that removes noop landing pads and replaces jumps to them with
-/// `None`. This is important because otherwise LLVM generates terrible
-/// code for these.
+/// `UnwindAction::Continue`. This is important because otherwise LLVM generates
+/// terrible code for these.
 pub struct RemoveNoopLandingPads;
 
 impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads {
@@ -63,7 +63,7 @@ impl RemoveNoopLandingPads {
         let terminator = body[bb].terminator();
         match terminator.kind {
             TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
+            | TerminatorKind::UnwindResume
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. } => {
@@ -72,7 +72,7 @@ impl RemoveNoopLandingPads {
             TerminatorKind::GeneratorDrop
             | TerminatorKind::Yield { .. }
             | TerminatorKind::Return
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Unreachable
             | TerminatorKind::Call { .. }
             | TerminatorKind::Assert { .. }
@@ -84,7 +84,17 @@ impl RemoveNoopLandingPads {
     fn remove_nop_landing_pads(&self, body: &mut Body<'_>) {
         debug!("body: {:#?}", body);
 
-        // make sure there's a resume block
+        // Skip the pass if there are no blocks with a resume terminator.
+        let has_resume = body
+            .basic_blocks
+            .iter_enumerated()
+            .any(|(_bb, block)| matches!(block.terminator().kind, TerminatorKind::UnwindResume));
+        if !has_resume {
+            debug!("remove_noop_landing_pads: no resume block in MIR");
+            return;
+        }
+
+        // make sure there's a resume block without any statements
         let resume_block = {
             let mut patch = MirPatch::new(body);
             let resume_block = patch.resume_block();
diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
index 6f9edd07d73..26384974798 100644
--- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
+++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
@@ -4,7 +4,9 @@ use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, VariantDef};
 use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
 use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
-use rustc_mir_dataflow::{self, move_path_children_matching, Analysis, MoveDataParamEnv};
+use rustc_mir_dataflow::{
+    self, move_path_children_matching, Analysis, MaybeReachable, MoveDataParamEnv,
+};
 use rustc_target::abi::FieldIdx;
 
 use crate::MirPass;
@@ -41,6 +43,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUninitDrops {
             let TerminatorKind::Drop { place, .. } = &terminator.kind else { continue };
 
             maybe_inits.seek_before_primary_effect(body.terminator_loc(bb));
+            let MaybeReachable::Reachable(maybe_inits) = maybe_inits.get() else { continue };
 
             // If there's no move path for the dropped place, it's probably a `Deref`. Let it alone.
             let LookupResult::Exact(mpi) = mdpe.move_data.rev_lookup.find(place.as_ref()) else {
@@ -50,7 +53,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUninitDrops {
             let should_keep = is_needs_drop_and_init(
                 tcx,
                 param_env,
-                maybe_inits.get(),
+                maybe_inits,
                 &mdpe.move_data,
                 place.ty(body, tcx).ty,
                 mpi,
diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs
index 1d8e54cdca0..de1b80585d1 100644
--- a/compiler/rustc_mir_transform/src/separate_const_switch.rs
+++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs
@@ -108,13 +108,13 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize {
                         }
 
                         // The following terminators are not allowed
-                        TerminatorKind::Resume
+                        TerminatorKind::UnwindResume
                         | TerminatorKind::Drop { .. }
                         | TerminatorKind::Call { .. }
                         | TerminatorKind::Assert { .. }
                         | TerminatorKind::FalseUnwind { .. }
                         | TerminatorKind::Yield { .. }
-                        | TerminatorKind::Terminate
+                        | TerminatorKind::UnwindTerminate
                         | TerminatorKind::Return
                         | TerminatorKind::Unreachable
                         | TerminatorKind::InlineAsm { .. }
@@ -165,8 +165,8 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize {
                 });
             }
 
-            TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | 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 5e8ba4f544c..046eed2dd19 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -71,8 +71,17 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
             // of this function. Is this intentional?
             if let Some(ty::Generator(gen_def_id, args, _)) = ty.map(Ty::kind) {
                 let body = tcx.optimized_mir(*gen_def_id).generator_drop().unwrap();
-                let body = EarlyBinder::bind(body.clone()).instantiate(tcx, args);
+                let mut body = EarlyBinder::bind(body.clone()).instantiate(tcx, args);
                 debug!("make_shim({:?}) = {:?}", instance, body);
+
+                // Run empty passes to mark phase change and perform validation.
+                pm::run_passes(
+                    tcx,
+                    &mut body,
+                    &[],
+                    Some(MirPhase::Runtime(RuntimePhase::Optimized)),
+                );
+
                 return body;
             }
 
@@ -574,7 +583,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
         I: IntoIterator<Item = Ty<'tcx>>,
     {
         self.block(vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false);
-        let unwind = self.block(vec![], TerminatorKind::Resume, true);
+        let unwind = self.block(vec![], TerminatorKind::UnwindResume, true);
         let target = self.block(vec![], TerminatorKind::Return, false);
 
         let _final_cleanup_block = self.clone_fields(dest, src, target, unwind, tys);
@@ -588,7 +597,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
         args: GeneratorArgs<'tcx>,
     ) {
         self.block(vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false);
-        let unwind = self.block(vec![], TerminatorKind::Resume, true);
+        let unwind = self.block(vec![], TerminatorKind::UnwindResume, true);
         // This will get overwritten with a switch once we know the target blocks
         let switch = self.block(vec![], TerminatorKind::Unreachable, false);
         let unwind = self.clone_fields(dest, src, switch, unwind, args.upvar_tys());
@@ -845,7 +854,7 @@ fn build_call_shim<'tcx>(
         );
 
         // BB #4 - resume
-        block(&mut blocks, vec![], TerminatorKind::Resume, true);
+        block(&mut blocks, vec![], TerminatorKind::UnwindResume, true);
     }
 
     let mut body =
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 55b14ce1c3e..cd7908e75e2 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -776,7 +776,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
                     self.output.push(create_fn_mono_item(tcx, instance, source));
                 }
             }
-            mir::TerminatorKind::Terminate { .. } => {
+            mir::TerminatorKind::UnwindTerminate { .. } => {
                 let instance = Instance::mono(
                     tcx,
                     tcx.require_lang_item(LangItem::PanicCannotUnwind, Some(source)),
@@ -787,7 +787,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
             }
             mir::TerminatorKind::Goto { .. }
             | mir::TerminatorKind::SwitchInt { .. }
-            | mir::TerminatorKind::Resume
+            | mir::TerminatorKind::UnwindResume
             | mir::TerminatorKind::Return
             | mir::TerminatorKind::Unreachable => {}
             mir::TerminatorKind::GeneratorDrop
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 6888127f36c..34cc0998c9b 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -310,8 +310,8 @@ parse_inclusive_range_no_end = inclusive range with no end
     .suggestion_open_range = use `..` instead
     .note = inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-parse_incorrect_braces_trait_bounds = incorrect braces around trait bounds
-    .suggestion = remove the parentheses
+parse_incorrect_parens_trait_bounds = incorrect parentheses around trait bounds
+parse_incorrect_parens_trait_bounds_sugg = fix the parentheses
 
 parse_incorrect_semicolon =
     expected item, found `;`
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 26f38c9156a..e0b1e3678e4 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -2636,21 +2636,24 @@ pub(crate) struct MissingPlusBounds {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_incorrect_braces_trait_bounds)]
-pub(crate) struct IncorrectBracesTraitBounds {
+#[diag(parse_incorrect_parens_trait_bounds)]
+pub(crate) struct IncorrectParensTraitBounds {
     #[primary_span]
     pub span: Vec<Span>,
     #[subdiagnostic]
-    pub sugg: IncorrectBracesTraitBoundsSugg,
+    pub sugg: IncorrectParensTraitBoundsSugg,
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
-pub(crate) struct IncorrectBracesTraitBoundsSugg {
+#[multipart_suggestion(
+    parse_incorrect_parens_trait_bounds_sugg,
+    applicability = "machine-applicable"
+)]
+pub(crate) struct IncorrectParensTraitBoundsSugg {
     #[suggestion_part(code = " ")]
-    pub l: Span,
-    #[suggestion_part(code = "")]
-    pub r: Span,
+    pub wrong_span: Span,
+    #[suggestion_part(code = "(")]
+    pub new_span: Span,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
index 446472d1294..b659c40b233 100644
--- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
+++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
@@ -80,20 +80,14 @@ pub(crate) fn emit_unescape_error(
             let sugg = sugg.unwrap_or_else(|| {
                 let prefix = mode.prefix_noraw();
                 let mut escaped = String::with_capacity(lit.len());
-                let mut chrs = lit.chars().peekable();
-                while let Some(first) = chrs.next() {
-                    match (first, chrs.peek()) {
-                        ('\\', Some('"')) => {
-                            escaped.push('\\');
-                            escaped.push('"');
-                            chrs.next();
-                        }
-                        ('"', _) => {
-                            escaped.push('\\');
-                            escaped.push('"')
-                        }
-                        (c, _) => escaped.push(c),
-                    };
+                let mut in_escape = false;
+                for c in lit.chars() {
+                    match c {
+                        '\\' => in_escape = !in_escape,
+                        '"' if !in_escape => escaped.push('\\'),
+                        _ => in_escape = false,
+                    }
+                    escaped.push(c);
                 }
                 let sugg = format!("{prefix}\"{escaped}\"");
                 MoreThanOneCharSugg::Quotes {
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index e409c7c6781..9ae3ef6172c 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -22,6 +22,7 @@ use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty
 use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
 use rustc_ast::{ClosureBinder, MetaItemLit, StmtKind};
 use rustc_ast_pretty::pprust;
+use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{
     AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic,
     PResult, StashKey,
@@ -193,13 +194,7 @@ impl<'a> Parser<'a> {
 
         self.expected_tokens.push(TokenType::Operator);
         while let Some(op) = self.check_assoc_op() {
-            // Adjust the span for interpolated LHS to point to the `$lhs` token
-            // and not to what it refers to.
-            let lhs_span = match self.prev_token.kind {
-                TokenKind::Interpolated(..) => self.prev_token.span,
-                _ => lhs.span,
-            };
-
+            let lhs_span = self.interpolated_or_expr_span(&lhs);
             let cur_op_span = self.token.span;
             let restrictions = if op.node.is_assign_like() {
                 self.restrictions & Restrictions::NO_STRUCT_LITERAL
@@ -626,8 +621,8 @@ impl<'a> Parser<'a> {
 
     fn parse_expr_prefix_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)> {
         self.bump();
-        let expr = self.parse_expr_prefix(None);
-        let (span, expr) = self.interpolated_or_expr_span(expr)?;
+        let expr = self.parse_expr_prefix(None)?;
+        let span = self.interpolated_or_expr_span(&expr);
         Ok((lo.to(span), expr))
     }
 
@@ -702,20 +697,12 @@ impl<'a> Parser<'a> {
         self.parse_expr_unary(lo, UnOp::Not)
     }
 
-    /// Returns the span of expr, if it was not interpolated or the span of the interpolated token.
-    fn interpolated_or_expr_span(
-        &self,
-        expr: PResult<'a, P<Expr>>,
-    ) -> PResult<'a, (Span, P<Expr>)> {
-        expr.map(|e| {
-            (
-                match self.prev_token.kind {
-                    TokenKind::Interpolated(..) => self.prev_token.span,
-                    _ => e.span,
-                },
-                e,
-            )
-        })
+    /// Returns the span of expr if it was not interpolated, or the span of the interpolated token.
+    fn interpolated_or_expr_span(&self, expr: &Expr) -> Span {
+        match self.prev_token.kind {
+            TokenKind::Interpolated(..) => self.prev_token.span,
+            _ => expr.span,
+        }
     }
 
     fn parse_assoc_op_cast(
@@ -898,8 +885,8 @@ impl<'a> Parser<'a> {
             self.parse_expr_prefix_range(None)
         } else {
             self.parse_expr_prefix(None)
-        };
-        let (hi, expr) = self.interpolated_or_expr_span(expr)?;
+        }?;
+        let hi = self.interpolated_or_expr_span(&expr);
         let span = lo.to(hi);
         if let Some(lt) = lifetime {
             self.error_remove_borrow_lifetime(span, lt.ident.span);
@@ -930,8 +917,8 @@ impl<'a> Parser<'a> {
     fn parse_expr_dot_or_call(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
         let attrs = self.parse_or_use_outer_attributes(attrs)?;
         self.collect_tokens_for_expr(attrs, |this, attrs| {
-            let base = this.parse_expr_bottom();
-            let (span, base) = this.interpolated_or_expr_span(base)?;
+            let base = this.parse_expr_bottom()?;
+            let span = this.interpolated_or_expr_span(&base);
             this.parse_expr_dot_or_call_with(base, span, attrs)
         })
     }
@@ -2503,7 +2490,7 @@ impl<'a> Parser<'a> {
         let else_span = self.prev_token.span; // `else`
         let attrs = self.parse_outer_attributes()?; // For recovery.
         let expr = if self.eat_keyword(kw::If) {
-            self.parse_expr_if()?
+            ensure_sufficient_stack(|| self.parse_expr_if())?
         } else if self.check(&TokenKind::OpenDelim(Delimiter::Brace)) {
             self.parse_simple_block()?
         } else {
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index ce4d4a60551..77c59bb3881 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1052,33 +1052,48 @@ impl<'a> Parser<'a> {
     }
 
     /// Look-ahead `dist` tokens of `self.token` and get access to that token there.
-    /// When `dist == 0` then the current token is looked at.
+    /// When `dist == 0` then the current token is looked at. `Eof` will be
+    /// returned if the look-ahead is any distance past the end of the tokens.
     pub fn look_ahead<R>(&self, dist: usize, looker: impl FnOnce(&Token) -> R) -> R {
         if dist == 0 {
             return looker(&self.token);
         }
 
-        let tree_cursor = &self.token_cursor.tree_cursor;
         if let Some(&(_, delim, span)) = self.token_cursor.stack.last()
             && delim != Delimiter::Invisible
         {
+            // We are not in the outermost token stream, and the token stream
+            // we are in has non-skipped delimiters. Look for skipped
+            // delimiters in the lookahead range.
+            let tree_cursor = &self.token_cursor.tree_cursor;
             let all_normal = (0..dist).all(|i| {
                 let token = tree_cursor.look_ahead(i);
                 !matches!(token, Some(TokenTree::Delimited(_, Delimiter::Invisible, _)))
             });
             if all_normal {
+                // There were no skipped delimiters. Do lookahead by plain indexing.
                 return match tree_cursor.look_ahead(dist - 1) {
-                    Some(tree) => match tree {
-                        TokenTree::Token(token, _) => looker(token),
-                        TokenTree::Delimited(dspan, delim, _) => {
-                            looker(&Token::new(token::OpenDelim(*delim), dspan.open))
+                    Some(tree) => {
+                        // Indexing stayed within the current token stream.
+                        match tree {
+                            TokenTree::Token(token, _) => looker(token),
+                            TokenTree::Delimited(dspan, delim, _) => {
+                                looker(&Token::new(token::OpenDelim(*delim), dspan.open))
+                            }
                         }
-                    },
-                    None => looker(&Token::new(token::CloseDelim(delim), span.close)),
+                    }
+                    None => {
+                        // Indexing went past the end of the current token
+                        // stream. Use the close delimiter, no matter how far
+                        // ahead `dist` went.
+                        looker(&Token::new(token::CloseDelim(delim), span.close))
+                    }
                 };
             }
         }
 
+        // We are in a more complex case. Just clone the token cursor and use
+        // `next`, skipping delimiters as necessary. Slow but simple.
         let mut cursor = self.token_cursor.clone();
         let mut i = 0;
         let mut token = Token::dummy();
@@ -1476,7 +1491,7 @@ pub enum FlatToken {
 }
 
 #[derive(Debug)]
-pub enum NtOrTt {
+pub enum ParseNtResult {
     Nt(Nonterminal),
     Tt(TokenTree),
 }
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index f5681532b3a..ff059a7e865 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -1,5 +1,5 @@
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, Delimiter, NonterminalKind, Token};
+use rustc_ast::token::{self, Delimiter, Nonterminal::*, NonterminalKind, Token};
 use rustc_ast::HasTokens;
 use rustc_ast_pretty::pprust;
 use rustc_errors::IntoDiagnostic;
@@ -8,7 +8,7 @@ use rustc_span::symbol::{kw, Ident};
 
 use crate::errors::UnexpectedNonterminal;
 use crate::parser::pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
-use crate::parser::{FollowedByType, ForceCollect, NtOrTt, Parser, PathStyle};
+use crate::parser::{FollowedByType, ForceCollect, ParseNtResult, Parser, PathStyle};
 
 impl<'a> Parser<'a> {
     /// Checks whether a non-terminal may begin with a particular token.
@@ -20,10 +20,21 @@ impl<'a> Parser<'a> {
     pub fn nonterminal_may_begin_with(kind: NonterminalKind, token: &Token) -> bool {
         /// Checks whether the non-terminal may contain a single (non-keyword) identifier.
         fn may_be_ident(nt: &token::Nonterminal) -> bool {
-            !matches!(
-                *nt,
-                token::NtItem(_) | token::NtBlock(_) | token::NtVis(_) | token::NtLifetime(_)
-            )
+            match nt {
+                NtStmt(_)
+                | NtPat(_)
+                | NtExpr(_)
+                | NtTy(_)
+                | NtIdent(..)
+                | NtLiteral(_) // `true`, `false`
+                | NtMeta(_)
+                | NtPath(_) => true,
+
+                NtItem(_)
+                | NtBlock(_)
+                | NtVis(_)
+                | NtLifetime(_) => false,
+            }
         }
 
         match kind {
@@ -44,27 +55,19 @@ impl<'a> Parser<'a> {
             },
             NonterminalKind::Block => match &token.kind {
                 token::OpenDelim(Delimiter::Brace) => true,
-                token::Interpolated(nt) => !matches!(
-                    **nt,
-                    token::NtItem(_)
-                        | token::NtPat(_)
-                        | token::NtTy(_)
-                        | token::NtIdent(..)
-                        | token::NtMeta(_)
-                        | token::NtPath(_)
-                        | token::NtVis(_)
-                ),
+                token::Interpolated(nt) => match **nt {
+                    NtBlock(_) | NtLifetime(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true,
+                    NtItem(_) | NtPat(_) | NtTy(_) | NtIdent(..) | NtMeta(_) | NtPath(_)
+                    | NtVis(_) => false,
+                },
                 _ => false,
             },
             NonterminalKind::Path | NonterminalKind::Meta => match &token.kind {
                 token::ModSep | token::Ident(..) => true,
-                token::Interpolated(nt) => match **nt {
-                    token::NtPath(_) | token::NtMeta(_) => true,
-                    _ => may_be_ident(&nt),
-                },
+                token::Interpolated(nt) => may_be_ident(nt),
                 _ => false,
             },
-            NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => {
+            NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => {
                 match &token.kind {
                 token::Ident(..) |                          // box, ref, mut, and other identifiers (can stricten)
                 token::OpenDelim(Delimiter::Parenthesis) |  // tuple pattern
@@ -79,7 +82,7 @@ impl<'a> Parser<'a> {
                 token::Lt |                                 // path (UFCS constant)
                 token::BinOp(token::Shl) => true,           // path (double UFCS)
                 // leading vert `|` or-pattern
-                token::BinOp(token::Or) =>  matches!(kind, NonterminalKind::PatWithOr {..}),
+                token::BinOp(token::Or) => matches!(kind, NonterminalKind::PatWithOr),
                 token::Interpolated(nt) => may_be_ident(nt),
                 _ => false,
             }
@@ -87,7 +90,7 @@ impl<'a> Parser<'a> {
             NonterminalKind::Lifetime => match &token.kind {
                 token::Lifetime(_) => true,
                 token::Interpolated(nt) => {
-                    matches!(**nt, token::NtLifetime(_))
+                    matches!(**nt, NtLifetime(_))
                 }
                 _ => false,
             },
@@ -100,18 +103,16 @@ impl<'a> Parser<'a> {
     /// Parse a non-terminal (e.g. MBE `:pat` or `:ident`). Inlined because there is only one call
     /// site.
     #[inline]
-    pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, NtOrTt> {
-        // Any `Nonterminal` which stores its tokens (currently `NtItem` and `NtExpr`)
-        // needs to have them force-captured here.
+    pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, ParseNtResult> {
         // A `macro_rules!` invocation may pass a captured item/expr to a proc-macro,
         // which requires having captured tokens available. Since we cannot determine
         // in advance whether or not a proc-macro will be (transitively) invoked,
         // we always capture tokens for any `Nonterminal` which needs them.
         let mut nt = match kind {
             // Note that TT is treated differently to all the others.
-            NonterminalKind::TT => return Ok(NtOrTt::Tt(self.parse_token_tree())),
+            NonterminalKind::TT => return Ok(ParseNtResult::Tt(self.parse_token_tree())),
             NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? {
-                Some(item) => token::NtItem(item),
+                Some(item) => NtItem(item),
                 None => {
                     return Err(UnexpectedNonterminal::Item(self.token.span)
                                .into_diagnostic(&self.sess.span_diagnostic));
@@ -120,19 +121,19 @@ impl<'a> Parser<'a> {
             NonterminalKind::Block => {
                 // While a block *expression* may have attributes (e.g. `#[my_attr] { ... }`),
                 // the ':block' matcher does not support them
-                token::NtBlock(self.collect_tokens_no_attrs(|this| this.parse_block())?)
+                NtBlock(self.collect_tokens_no_attrs(|this| this.parse_block())?)
             }
             NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? {
-                Some(s) => token::NtStmt(P(s)),
+                Some(s) => NtStmt(P(s)),
                 None => {
                     return Err(UnexpectedNonterminal::Statement(self.token.span)
                                .into_diagnostic(&self.sess.span_diagnostic));
                 }
             },
-            NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => {
-                token::NtPat(self.collect_tokens_no_attrs(|this| match kind {
+            NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => {
+                NtPat(self.collect_tokens_no_attrs(|this| match kind {
                     NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None, None),
-                    NonterminalKind::PatWithOr { .. } => this.parse_pat_allow_top_alt(
+                    NonterminalKind::PatWithOr => this.parse_pat_allow_top_alt(
                         None,
                         RecoverComma::No,
                         RecoverColon::No,
@@ -142,16 +143,16 @@ impl<'a> Parser<'a> {
                 })?)
             }
 
-            NonterminalKind::Expr => token::NtExpr(self.parse_expr_force_collect()?),
+            NonterminalKind::Expr => NtExpr(self.parse_expr_force_collect()?),
             NonterminalKind::Literal => {
                 // The `:literal` matcher does not support attributes
-                token::NtLiteral(
+                NtLiteral(
                     self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?,
                 )
             }
 
-            NonterminalKind::Ty => token::NtTy(
-                self.collect_tokens_no_attrs(|this| this.parse_no_question_mark_recover())?,
+            NonterminalKind::Ty => NtTy(
+                self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?,
             ),
 
             // this could be handled like a token, since it is one
@@ -159,7 +160,7 @@ impl<'a> Parser<'a> {
                 if let Some((ident, is_raw)) = get_macro_ident(&self.token) =>
             {
                 self.bump();
-                token::NtIdent(ident, is_raw)
+                NtIdent(ident, is_raw)
             }
             NonterminalKind::Ident => {
                 return Err(UnexpectedNonterminal::Ident {
@@ -167,16 +168,16 @@ impl<'a> Parser<'a> {
                     token: self.token.clone(),
                 }.into_diagnostic(&self.sess.span_diagnostic));
             }
-            NonterminalKind::Path => token::NtPath(
+            NonterminalKind::Path => NtPath(
                 P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?),
             ),
-            NonterminalKind::Meta => token::NtMeta(P(self.parse_attr_item(true)?)),
-            NonterminalKind::Vis => token::NtVis(
+            NonterminalKind::Meta => NtMeta(P(self.parse_attr_item(true)?)),
+            NonterminalKind::Vis => NtVis(
                 P(self.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?),
             ),
             NonterminalKind::Lifetime => {
                 if self.check_lifetime() {
-                    token::NtLifetime(self.expect_lifetime().ident)
+                    NtLifetime(self.expect_lifetime().ident)
                 } else {
                     return Err(UnexpectedNonterminal::Lifetime {
                         span: self.token.span,
@@ -196,7 +197,7 @@ impl<'a> Parser<'a> {
             );
         }
 
-        Ok(NtOrTt::Nt(nt))
+        Ok(ParseNtResult::Nt(nt))
     }
 }
 
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 3bb50b05aa3..2d888efb1f3 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -180,7 +180,7 @@ impl<'a> Parser<'a> {
         )
     }
 
-    pub(super) fn parse_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>> {
+    pub(super) fn parse_ty_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>> {
         self.parse_ty_common(
             AllowPlus::Yes,
             AllowCVariadic::No,
@@ -714,6 +714,7 @@ impl<'a> Parser<'a> {
     /// ```
     fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> {
         let lo = self.token.span;
+        let leading_token = self.prev_token.clone();
         let has_parens = self.eat(&token::OpenDelim(Delimiter::Parenthesis));
         let inner_lo = self.token.span;
 
@@ -722,7 +723,7 @@ impl<'a> Parser<'a> {
             self.error_lt_bound_with_modifiers(modifiers);
             self.parse_generic_lt_bound(lo, inner_lo, has_parens)?
         } else {
-            self.parse_generic_ty_bound(lo, has_parens, modifiers)?
+            self.parse_generic_ty_bound(lo, has_parens, modifiers, &leading_token)?
         };
 
         Ok(bound)
@@ -827,6 +828,7 @@ impl<'a> Parser<'a> {
         lo: Span,
         has_parens: bool,
         modifiers: BoundModifiers,
+        leading_token: &Token,
     ) -> PResult<'a, GenericBound> {
         let mut lifetime_defs = self.parse_late_bound_lifetime_defs()?;
         let mut path = if self.token.is_keyword(kw::Fn)
@@ -873,18 +875,18 @@ impl<'a> Parser<'a> {
         }
 
         if has_parens {
-            if self.token.is_like_plus() {
-                // Someone has written something like `&dyn (Trait + Other)`. The correct code
-                // would be `&(dyn Trait + Other)`, but we don't have access to the appropriate
-                // span to suggest that. When written as `&dyn Trait + Other`, an appropriate
-                // suggestion is given.
+            // Someone has written something like `&dyn (Trait + Other)`. The correct code
+            // would be `&(dyn Trait + Other)`
+            if self.token.is_like_plus() && leading_token.is_keyword(kw::Dyn) {
                 let bounds = vec![];
                 self.parse_remaining_bounds(bounds, true)?;
                 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
-                let sp = vec![lo, self.prev_token.span];
-                self.sess.emit_err(errors::IncorrectBracesTraitBounds {
-                    span: sp,
-                    sugg: errors::IncorrectBracesTraitBoundsSugg { l: lo, r: self.prev_token.span },
+                self.sess.emit_err(errors::IncorrectParensTraitBounds {
+                    span: vec![lo, self.prev_token.span],
+                    sugg: errors::IncorrectParensTraitBoundsSugg {
+                        wrong_span: leading_token.span.shrink_to_hi().to(lo),
+                        new_span: leading_token.span.shrink_to_lo(),
+                    },
                 });
             } else {
                 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index 0463ee2914b..a7a8af864ac 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -27,7 +27,6 @@ pub fn test_layout(tcx: TyCtxt<'_>) {
 }
 
 fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
-    let tcx = tcx;
     let param_env = tcx.param_env(item_def_id);
     let ty = tcx.type_of(item_def_id).instantiate_identity();
     match tcx.layout_of(param_env.and(ty)) {
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 0c0b8b6d094..20e996eaec4 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -1105,7 +1105,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                 }
 
                 // Then do a second pass for inputs
-                let mut succ = succ;
                 for (op, _op_sp) in asm.operands.iter().rev() {
                     match op {
                         hir::InlineAsmOperand::In { expr, .. } => {
diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs
index 9a09f516ec9..4ba9d53a92f 100644
--- a/compiler/rustc_query_system/src/query/caches.rs
+++ b/compiler/rustc_query_system/src/query/caches.rs
@@ -1,9 +1,7 @@
 use crate::dep_graph::DepNodeIndex;
 
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sharded;
-#[cfg(parallel_compiler)]
-use rustc_data_structures::sharded::Sharded;
+use rustc_data_structures::sharded::{self, Sharded};
 use rustc_data_structures::sync::Lock;
 use rustc_index::{Idx, IndexVec};
 use std::fmt::Debug;
@@ -37,10 +35,7 @@ impl<'tcx, K: Eq + Hash, V: 'tcx> CacheSelector<'tcx, V> for DefaultCacheSelecto
 }
 
 pub struct DefaultCache<K, V> {
-    #[cfg(parallel_compiler)]
     cache: Sharded<FxHashMap<K, (V, DepNodeIndex)>>,
-    #[cfg(not(parallel_compiler))]
-    cache: Lock<FxHashMap<K, (V, DepNodeIndex)>>,
 }
 
 impl<K, V> Default for DefaultCache<K, V> {
@@ -60,10 +55,7 @@ where
     #[inline(always)]
     fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> {
         let key_hash = sharded::make_hash(key);
-        #[cfg(parallel_compiler)]
         let lock = self.cache.get_shard_by_hash(key_hash).lock();
-        #[cfg(not(parallel_compiler))]
-        let lock = self.cache.lock();
         let result = lock.raw_entry().from_key_hashed_nocheck(key_hash, key);
 
         if let Some((_, value)) = result { Some(*value) } else { None }
@@ -71,29 +63,16 @@ where
 
     #[inline]
     fn complete(&self, key: K, value: V, index: DepNodeIndex) {
-        #[cfg(parallel_compiler)]
         let mut lock = self.cache.get_shard_by_value(&key).lock();
-        #[cfg(not(parallel_compiler))]
-        let mut lock = self.cache.lock();
         // We may be overwriting another value. This is all right, since the dep-graph
         // will check that the fingerprint matches.
         lock.insert(key, (value, index));
     }
 
     fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
-        #[cfg(parallel_compiler)]
-        {
-            let shards = self.cache.lock_shards();
-            for shard in shards.iter() {
-                for (k, v) in shard.iter() {
-                    f(k, &v.0, v.1);
-                }
-            }
-        }
-        #[cfg(not(parallel_compiler))]
-        {
-            let map = self.cache.lock();
-            for (k, v) in map.iter() {
+        let shards = self.cache.lock_shards();
+        for shard in shards.iter() {
+            for (k, v) in shard.iter() {
                 f(k, &v.0, v.1);
             }
         }
@@ -151,10 +130,7 @@ impl<'tcx, K: Idx, V: 'tcx> CacheSelector<'tcx, V> for VecCacheSelector<K> {
 }
 
 pub struct VecCache<K: Idx, V> {
-    #[cfg(parallel_compiler)]
     cache: Sharded<IndexVec<K, Option<(V, DepNodeIndex)>>>,
-    #[cfg(not(parallel_compiler))]
-    cache: Lock<IndexVec<K, Option<(V, DepNodeIndex)>>>,
 }
 
 impl<K: Idx, V> Default for VecCache<K, V> {
@@ -173,38 +149,20 @@ where
 
     #[inline(always)]
     fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> {
-        #[cfg(parallel_compiler)]
         let lock = self.cache.get_shard_by_hash(key.index() as u64).lock();
-        #[cfg(not(parallel_compiler))]
-        let lock = self.cache.lock();
         if let Some(Some(value)) = lock.get(*key) { Some(*value) } else { None }
     }
 
     #[inline]
     fn complete(&self, key: K, value: V, index: DepNodeIndex) {
-        #[cfg(parallel_compiler)]
         let mut lock = self.cache.get_shard_by_hash(key.index() as u64).lock();
-        #[cfg(not(parallel_compiler))]
-        let mut lock = self.cache.lock();
         lock.insert(key, (value, index));
     }
 
     fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
-        #[cfg(parallel_compiler)]
-        {
-            let shards = self.cache.lock_shards();
-            for shard in shards.iter() {
-                for (k, v) in shard.iter_enumerated() {
-                    if let Some(v) = v {
-                        f(&k, &v.0, v.1);
-                    }
-                }
-            }
-        }
-        #[cfg(not(parallel_compiler))]
-        {
-            let map = self.cache.lock();
-            for (k, v) in map.iter_enumerated() {
+        let shards = self.cache.lock_shards();
+        for shard in shards.iter() {
+            for (k, v) in shard.iter_enumerated() {
                 if let Some(v) = v {
                     f(&k, &v.0, v.1);
                 }
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
index d433391f272..ba7417b6dda 100644
--- a/compiler/rustc_resolve/src/rustdoc.rs
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -1,4 +1,4 @@
-use pulldown_cmark::{BrokenLink, Event, LinkType, Options, Parser, Tag};
+use pulldown_cmark::{BrokenLink, CowStr, Event, LinkType, Options, Parser, Tag};
 use rustc_ast as ast;
 use rustc_ast::util::comments::beautify_doc_string;
 use rustc_data_structures::fx::FxHashMap;
@@ -392,16 +392,73 @@ pub(crate) fn attrs_to_preprocessed_links(attrs: &[ast::Attribute]) -> Vec<Box<s
     let (doc_fragments, _) = attrs_to_doc_fragments(attrs.iter().map(|attr| (attr, None)), true);
     let doc = prepare_to_doc_link_resolution(&doc_fragments).into_values().next().unwrap();
 
-    Parser::new_with_broken_link_callback(
+    parse_links(&doc)
+}
+
+/// Similiar version of `markdown_links` from rustdoc.
+/// This will collect destination links and display text if exists.
+fn parse_links<'md>(doc: &'md str) -> Vec<Box<str>> {
+    let mut broken_link_callback = |link: BrokenLink<'md>| Some((link.reference, "".into()));
+    let mut event_iter = Parser::new_with_broken_link_callback(
         &doc,
         main_body_opts(),
-        Some(&mut |link: BrokenLink<'_>| Some((link.reference, "".into()))),
+        Some(&mut broken_link_callback),
     )
-    .filter_map(|event| match event {
-        Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
-            Some(preprocess_link(&dest))
+    .into_iter();
+    let mut links = Vec::new();
+
+    while let Some(event) = event_iter.next() {
+        match event {
+            Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
+                if matches!(
+                    link_type,
+                    LinkType::Inline
+                        | LinkType::ReferenceUnknown
+                        | LinkType::Reference
+                        | LinkType::Shortcut
+                        | LinkType::ShortcutUnknown
+                ) {
+                    if let Some(display_text) = collect_link_data(&mut event_iter) {
+                        links.push(display_text);
+                    }
+                }
+
+                links.push(preprocess_link(&dest));
+            }
+            _ => {}
+        }
+    }
+
+    links
+}
+
+/// Collects additional data of link.
+fn collect_link_data<'input, 'callback>(
+    event_iter: &mut Parser<'input, 'callback>,
+) -> Option<Box<str>> {
+    let mut display_text: Option<String> = None;
+    let mut append_text = |text: CowStr<'_>| {
+        if let Some(display_text) = &mut display_text {
+            display_text.push_str(&text);
+        } else {
+            display_text = Some(text.to_string());
+        }
+    };
+
+    while let Some(event) = event_iter.next() {
+        match event {
+            Event::Text(text) => {
+                append_text(text);
+            }
+            Event::Code(code) => {
+                append_text(code);
+            }
+            Event::End(_) => {
+                break;
+            }
+            _ => {}
         }
-        _ => None,
-    })
-    .collect()
+    }
+
+    display_text.map(String::into_boxed_str)
 }
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 28ae88424ab..f00472f181d 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -12,7 +12,7 @@ use crate::{EarlyErrorHandler, Session};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey};
 use rustc_target::abi::Align;
-use rustc_target::spec::{PanicStrategy, SanitizerSet, SplitDebuginfo};
+use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet, SplitDebuginfo};
 use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS};
 
 use crate::parse::{CrateCheckConfig, CrateConfig};
@@ -1193,6 +1193,7 @@ fn default_configuration(sess: &Session) -> CrateConfig {
     let os = &sess.target.os;
     let env = &sess.target.env;
     let abi = &sess.target.abi;
+    let relocation_model = sess.target.relocation_model.desc_symbol();
     let vendor = &sess.target.vendor;
     let min_atomic_width = sess.target.min_atomic_width();
     let max_atomic_width = sess.target.max_atomic_width();
@@ -1218,6 +1219,9 @@ fn default_configuration(sess: &Session) -> CrateConfig {
     ret.insert((sym::target_pointer_width, Some(Symbol::intern(&wordsz))));
     ret.insert((sym::target_env, Some(Symbol::intern(env))));
     ret.insert((sym::target_abi, Some(Symbol::intern(abi))));
+    if sess.is_nightly_build() {
+        ret.insert((sym::relocation_model, Some(relocation_model)));
+    }
     ret.insert((sym::target_vendor, Some(Symbol::intern(vendor))));
     if sess.target.has_thread_local {
         ret.insert((sym::target_thread_local, None));
@@ -1415,6 +1419,8 @@ impl CrateCheckConfig {
             .into_iter()
             .map(|sanitizer| Symbol::intern(sanitizer.as_str().unwrap()));
 
+        let relocation_model_values = RelocModel::all();
+
         // Unknown possible values:
         //  - `feature`
         //  - `target_feature`
@@ -1453,6 +1459,10 @@ impl CrateCheckConfig {
             .entry(sym::target_has_atomic_equal_alignment)
             .or_insert_with(no_values)
             .extend(atomic_values);
+        self.expecteds
+            .entry(sym::relocation_model)
+            .or_insert_with(empty_values)
+            .extend(relocation_model_values);
 
         // Target specific values
         {
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 06b37008ebe..7e8ac9a141a 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -780,8 +780,8 @@ impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> {
                     .collect(),
                 otherwise: targets.otherwise().as_usize(),
             },
-            Resume => Terminator::Resume,
-            Terminate => Terminator::Abort,
+            UnwindResume => Terminator::Resume,
+            UnwindTerminate => Terminator::Abort,
             Return => Terminator::Return,
             Unreachable => Terminator::Unreachable,
             Drop { place, target, unwind, replace: _ } => Terminator::Drop {
diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs
index a74975cefc2..19061742b64 100644
--- a/compiler/rustc_smir/src/stable_mir/mod.rs
+++ b/compiler/rustc_smir/src/stable_mir/mod.rs
@@ -85,6 +85,22 @@ pub fn all_local_items() -> CrateItems {
     with(|cx| cx.all_local_items())
 }
 
+pub fn all_trait_decls() -> TraitDecls {
+    with(|cx| cx.all_trait_decls())
+}
+
+pub fn trait_decl(trait_def: &TraitDef) -> TraitDecl {
+    with(|cx| cx.trait_decl(trait_def))
+}
+
+pub fn all_trait_impls() -> ImplTraitDecls {
+    with(|cx| cx.all_trait_impls())
+}
+
+pub fn trait_impl(trait_impl: &ImplDef) -> ImplTrait {
+    with(|cx| cx.trait_impl(trait_impl))
+}
+
 pub trait Context {
     fn entry_fn(&mut self) -> Option<CrateItem>;
     /// Retrieve all items of the local crate that have a MIR associated with them.
diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs
index f8ff6741208..7a6601f09da 100644
--- a/compiler/rustc_smir/src/stable_mir/ty.rs
+++ b/compiler/rustc_smir/src/stable_mir/ty.rs
@@ -432,12 +432,14 @@ pub struct UnevaluatedConst {
     pub promoted: Option<Promoted>,
 }
 
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub enum TraitSpecializationKind {
     None,
     Marker,
     AlwaysApplicable,
 }
 
+#[derive(Clone, Debug)]
 pub struct TraitDecl {
     pub def_id: TraitDef,
     pub unsafety: Safety,
@@ -454,6 +456,7 @@ pub struct TraitDecl {
 
 pub type ImplTrait = EarlyBinder<TraitRef>;
 
+#[derive(Clone, Debug)]
 pub struct TraitRef {
     pub def_id: TraitDef,
     pub args: GenericArgs,
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index afee5c0fe2b..c24b8d9ec17 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -686,6 +686,12 @@ impl Span {
     }
 
     /// Walk down the expansion ancestors to find a span that's contained within `outer`.
+    ///
+    /// The span returned by this method may have a different [`SyntaxContext`] as `outer`.
+    /// If you need to extend the span, use [`find_ancestor_inside_same_ctxt`] instead,
+    /// because joining spans with different syntax contexts can create unexpected results.
+    ///
+    /// [`find_ancestor_inside_same_ctxt`]: Self::find_ancestor_inside_same_ctxt
     pub fn find_ancestor_inside(mut self, outer: Span) -> Option<Span> {
         while !outer.contains(self) {
             self = self.parent_callsite()?;
@@ -693,11 +699,34 @@ impl Span {
         Some(self)
     }
 
-    /// Like `find_ancestor_inside`, but specifically for when spans might not
-    /// overlaps. Take care when using this, and prefer `find_ancestor_inside`
-    /// when you know that the spans are nested (modulo macro expansion).
+    /// Walk down the expansion ancestors to find a span with the same [`SyntaxContext`] as
+    /// `other`.
+    ///
+    /// Like [`find_ancestor_inside_same_ctxt`], but specifically for when spans might not
+    /// overlap. Take care when using this, and prefer [`find_ancestor_inside`] or
+    /// [`find_ancestor_inside_same_ctxt`] when you know that the spans are nested (modulo
+    /// macro expansion).
+    ///
+    /// [`find_ancestor_inside`]: Self::find_ancestor_inside
+    /// [`find_ancestor_inside_same_ctxt`]: Self::find_ancestor_inside_same_ctxt
     pub fn find_ancestor_in_same_ctxt(mut self, other: Span) -> Option<Span> {
-        while !Span::eq_ctxt(self, other) {
+        while !self.eq_ctxt(other) {
+            self = self.parent_callsite()?;
+        }
+        Some(self)
+    }
+
+    /// Walk down the expansion ancestors to find a span that's contained within `outer` and
+    /// has the same [`SyntaxContext`] as `outer`.
+    ///
+    /// This method is the combination of [`find_ancestor_inside`] and
+    /// [`find_ancestor_in_same_ctxt`] and should be preferred when extending the returned span.
+    /// If you do not need to modify the span, use [`find_ancestor_inside`] instead.
+    ///
+    /// [`find_ancestor_inside`]: Self::find_ancestor_inside
+    /// [`find_ancestor_in_same_ctxt`]: Self::find_ancestor_in_same_ctxt
+    pub fn find_ancestor_inside_same_ctxt(mut self, outer: Span) -> Option<Span> {
+        while !outer.contains(self) || !self.eq_ctxt(outer) {
             self = self.parent_callsite()?;
         }
         Some(self)
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index a0daebf5baa..28a2dfebcfe 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -445,6 +445,7 @@ symbols! {
         bridge,
         bswap,
         builtin_syntax,
+        c,
         c_str,
         c_str_literals,
         c_unwind,
@@ -468,6 +469,7 @@ symbols! {
         cfg_hide,
         cfg_overflow_checks,
         cfg_panic,
+        cfg_relocation_model,
         cfg_sanitize,
         cfg_target_abi,
         cfg_target_compact,
@@ -543,6 +545,7 @@ symbols! {
         const_panic_fmt,
         const_param_ty,
         const_precise_live_drops,
+        const_ptr_cast,
         const_raw_ptr_deref,
         const_raw_ptr_to_usize_cast,
         const_refs_to_cell,
@@ -660,6 +663,7 @@ symbols! {
         dyn_metadata,
         dyn_star,
         dyn_trait,
+        dynamic_no_pic: "dynamic-no-pic",
         e,
         edition_panic,
         effects,
@@ -1114,6 +1118,8 @@ symbols! {
         path,
         pattern_parentheses,
         phantom_data,
+        pic,
+        pie,
         pin,
         platform_intrinsics,
         plugin,
@@ -1160,6 +1166,7 @@ symbols! {
         profiler_runtime,
         ptr,
         ptr_cast,
+        ptr_cast_const,
         ptr_cast_mut,
         ptr_const_is_null,
         ptr_from_mut,
@@ -1221,6 +1228,7 @@ symbols! {
         register_tool,
         relaxed_adts,
         relaxed_struct_unsize,
+        relocation_model,
         rem,
         rem_assign,
         repr,
@@ -1241,6 +1249,8 @@ symbols! {
         rintf64,
         riscv_target_feature,
         rlib,
+        ropi,
+        ropi_rwpi: "ropi-rwpi",
         rotate_left,
         rotate_right,
         roundevenf32,
@@ -1352,6 +1362,7 @@ symbols! {
         rustdoc_missing_doc_code_examples,
         rustfmt,
         rvalue_static_promotion,
+        rwpi,
         s,
         safety,
         sanitize,
diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs
index c0f1827ad3f..400030ca0c6 100644
--- a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs
@@ -11,6 +11,7 @@ pub fn target() -> Target {
             features: "+strict-align,+v6".into(),
             max_atomic_width: Some(64),
             mcount: "\u{1}__gnu_mcount_nc".into(),
+            llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()),
             ..super::linux_gnu_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs
index 79b8958c22a..6228fb15a83 100644
--- a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs
+++ b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs
@@ -11,6 +11,7 @@ pub fn target() -> Target {
             features: "+strict-align,+v6,+vfp2,-d32".into(),
             max_atomic_width: Some(64),
             mcount: "\u{1}__gnu_mcount_nc".into(),
+            llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()),
             ..super::linux_gnu_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs
index 4836f3cf720..1d66515a72e 100644
--- a/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs
@@ -13,6 +13,7 @@ pub fn target() -> Target {
             endian: Endian::Big,
             max_atomic_width: Some(64),
             mcount: "\u{1}__gnu_mcount_nc".into(),
+            llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()),
             ..super::linux_gnu_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs
index 1de63a920c8..cffebcc9581 100644
--- a/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs
@@ -12,6 +12,7 @@ pub fn target() -> Target {
             // Atomic operations provided by compiler-builtins
             max_atomic_width: Some(32),
             mcount: "\u{1}__gnu_mcount_nc".into(),
+            llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()),
             has_thumb_interworking: true,
             ..super::linux_gnu_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs b/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs
index b7cfccc8b3d..4a8aa31576f 100644
--- a/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs
@@ -13,6 +13,7 @@ pub fn target() -> Target {
             features: "+v6,+vfp2,-d32".into(),
             max_atomic_width: Some(64),
             mcount: "\u{1}__gnu_mcount_nc".into(),
+            llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()),
             ..super::freebsd_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs
index 903042d7e7a..73ae212a7a6 100644
--- a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs
@@ -14,6 +14,7 @@ pub fn target() -> Target {
             features: "+v7,+thumb2,+soft-float,-neon".into(),
             max_atomic_width: Some(64),
             mcount: "\u{1}__gnu_mcount_nc".into(),
+            llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()),
             ..super::linux_gnu_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index af2b96ccb51..31b6961bb62 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -42,7 +42,7 @@ use crate::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_fs_util::try_canonicalize;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::{kw, sym, Symbol};
 use serde_json::Value;
 use std::borrow::Cow;
 use std::collections::BTreeMap;
@@ -655,6 +655,43 @@ pub enum RelocModel {
     RopiRwpi,
 }
 
+impl RelocModel {
+    pub fn desc(&self) -> &str {
+        match *self {
+            RelocModel::Static => "static",
+            RelocModel::Pic => "pic",
+            RelocModel::Pie => "pie",
+            RelocModel::DynamicNoPic => "dynamic-no-pic",
+            RelocModel::Ropi => "ropi",
+            RelocModel::Rwpi => "rwpi",
+            RelocModel::RopiRwpi => "ropi-rwpi",
+        }
+    }
+    pub const fn desc_symbol(&self) -> Symbol {
+        match *self {
+            RelocModel::Static => kw::Static,
+            RelocModel::Pic => sym::pic,
+            RelocModel::Pie => sym::pie,
+            RelocModel::DynamicNoPic => sym::dynamic_no_pic,
+            RelocModel::Ropi => sym::ropi,
+            RelocModel::Rwpi => sym::rwpi,
+            RelocModel::RopiRwpi => sym::ropi_rwpi,
+        }
+    }
+
+    pub const fn all() -> [Symbol; 7] {
+        [
+            RelocModel::Static.desc_symbol(),
+            RelocModel::Pic.desc_symbol(),
+            RelocModel::Pie.desc_symbol(),
+            RelocModel::DynamicNoPic.desc_symbol(),
+            RelocModel::Ropi.desc_symbol(),
+            RelocModel::Rwpi.desc_symbol(),
+            RelocModel::RopiRwpi.desc_symbol(),
+        ]
+    }
+}
+
 impl FromStr for RelocModel {
     type Err = ();
 
@@ -674,16 +711,7 @@ impl FromStr for RelocModel {
 
 impl ToJson for RelocModel {
     fn to_json(&self) -> Json {
-        match *self {
-            RelocModel::Static => "static",
-            RelocModel::Pic => "pic",
-            RelocModel::Pie => "pie",
-            RelocModel::DynamicNoPic => "dynamic-no-pic",
-            RelocModel::Ropi => "ropi",
-            RelocModel::Rwpi => "rwpi",
-            RelocModel::RopiRwpi => "ropi-rwpi",
-        }
-        .to_json()
+        self.desc().to_json()
     }
 }
 
@@ -1922,6 +1950,9 @@ pub struct TargetOptions {
     /// Use platform dependent mcount function
     pub mcount: StaticCow<str>,
 
+    /// Use LLVM intrinsic for mcount function name
+    pub llvm_mcount_intrinsic: Option<StaticCow<str>>,
+
     /// LLVM ABI name, corresponds to the '-mabi' parameter available in multilib C compilers
     pub llvm_abiname: StaticCow<str>,
 
@@ -2183,6 +2214,7 @@ impl Default for TargetOptions {
             override_export_symbols: None,
             merge_functions: MergeFunctions::Aliases,
             mcount: "mcount".into(),
+            llvm_mcount_intrinsic: None,
             llvm_abiname: "".into(),
             relax_elf_relocations: false,
             llvm_args: cvs![],
@@ -2840,6 +2872,7 @@ impl Target {
         key!(override_export_symbols, opt_list);
         key!(merge_functions, MergeFunctions)?;
         key!(mcount = "target-mcount");
+        key!(llvm_mcount_intrinsic, optional);
         key!(llvm_abiname);
         key!(relax_elf_relocations, bool);
         key!(llvm_args, list);
@@ -3096,6 +3129,7 @@ impl ToJson for Target {
         target_option_val!(override_export_symbols);
         target_option_val!(merge_functions);
         target_option_val!(mcount, "target-mcount");
+        target_option_val!(llvm_mcount_intrinsic);
         target_option_val!(llvm_abiname);
         target_option_val!(relax_elf_relocations);
         target_option_val!(llvm_args);
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 0990b9bee90..523841951b0 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -215,7 +215,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         // created inside of the query directly instead of returning them to the
         // caller.
         let prev_universe = self.infcx.universe();
-        let universes_created_in_query = response.max_universe.index() + 1;
+        let universes_created_in_query = response.max_universe.index();
         for _ in 0..universes_created_in_query {
             self.infcx.create_next_universe();
         }
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 3d800421b76..06a1027e5df 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1214,7 +1214,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
 
             let projected_term = selcx.infcx.resolve_vars_if_possible(projected_term);
 
-            let mut result = if projected_term.has_projections() {
+            let result = if projected_term.has_projections() {
                 let mut normalizer = AssocTypeNormalizer::new(
                     selcx,
                     param_env,
@@ -1224,19 +1224,14 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
                 );
                 let normalized_ty = normalizer.fold(projected_term);
 
+                let mut deduped = SsoHashSet::with_capacity(projected_obligations.len());
+                projected_obligations.retain(|obligation| deduped.insert(obligation.clone()));
+
                 Normalized { value: normalized_ty, obligations: projected_obligations }
             } else {
                 Normalized { value: projected_term, obligations: projected_obligations }
             };
 
-            let mut deduped: SsoHashSet<_> = Default::default();
-            result.obligations.retain(|projected_obligation| {
-                if !deduped.insert(projected_obligation.clone()) {
-                    return false;
-                }
-                true
-            });
-
             if use_cache {
                 infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone());
             }
diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs
index 1a2d6d64eb0..f36f4ec8697 100644
--- a/compiler/rustc_type_ir/src/structural_impls.rs
+++ b/compiler/rustc_type_ir/src/structural_impls.rs
@@ -23,7 +23,6 @@ TrivialTypeTraversalImpls! {
     (),
     bool,
     usize,
-    u8,
     u16,
     u32,
     u64,
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 8697a77db3b..96b93830f96 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -2183,7 +2183,7 @@ impl dyn Error + Send {
         let err: Box<dyn Error> = self;
         <dyn Error>::downcast(err).map_err(|s| unsafe {
             // Reapply the `Send` marker.
-            mem::transmute::<Box<dyn Error>, Box<dyn Error + Send>>(s)
+            Box::from_raw(Box::into_raw(s) as *mut (dyn Error + Send))
         })
     }
 }
@@ -2197,7 +2197,7 @@ impl dyn Error + Send + Sync {
         let err: Box<dyn Error> = self;
         <dyn Error>::downcast(err).map_err(|s| unsafe {
             // Reapply the `Send + Sync` marker.
-            mem::transmute::<Box<dyn Error>, Box<dyn Error + Send + Sync>>(s)
+            Box::from_raw(Box::into_raw(s) as *mut (dyn Error + Send + Sync))
         })
     }
 }
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index cb8691aac13..ffe6d637387 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -58,7 +58,7 @@
 
 // To run alloc tests without x.py without ending up with two copies of alloc, Miri needs to be
 // able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
-// rustc itself never sets the feature, so this line has no affect there.
+// rustc itself never sets the feature, so this line has no effect there.
 #![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
 //
 #![allow(unused_attributes)]
@@ -89,6 +89,7 @@
 #![allow(explicit_outlives_requirements)]
 #![warn(multiple_supertrait_upcastable)]
 #![cfg_attr(not(bootstrap), allow(internal_features))]
+#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))]
 //
 // Library features:
 // tidy-alphabetical-start
diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
index 921ce850d1e..38f9f39fbf8 100644
--- a/library/alloc/src/str.rs
+++ b/library/alloc/src/str.rs
@@ -612,7 +612,7 @@ pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box<str> {
 }
 
 /// Converts the bytes while the bytes are still ascii.
-/// For better average performance, this is happens in chunks of `2*size_of::<usize>()`.
+/// For better average performance, this happens in chunks of `2*size_of::<usize>()`.
 /// Returns a vec with the converted bytes.
 #[inline]
 #[cfg(not(test))]
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index e2a2fe932ab..476a4fea54f 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -153,7 +153,7 @@ macro_rules! acquire {
 ///
 /// ## `Deref` behavior
 ///
-/// `Arc<T>` automatically dereferences to `T` (via the [`Deref`][deref] trait),
+/// `Arc<T>` automatically dereferences to `T` (via the [`Deref`] trait),
 /// so you can call `T`'s methods on a value of type `Arc<T>`. To avoid name
 /// clashes with `T`'s methods, the methods of `Arc<T>` itself are associated
 /// functions, called using [fully qualified syntax]:
@@ -187,7 +187,6 @@ macro_rules! acquire {
 /// [mutex]: ../../std/sync/struct.Mutex.html
 /// [rwlock]: ../../std/sync/struct.RwLock.html
 /// [atomic]: core::sync::atomic
-/// [deref]: core::ops::Deref
 /// [downgrade]: Arc::downgrade
 /// [upgrade]: Weak::upgrade
 /// [RefCell\<T>]: core::cell::RefCell
@@ -1495,7 +1494,7 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
     /// alignment as `T`. This is trivially true if `U` is `T`.
     /// Note that if `U` is not `T` but has the same size and alignment, this is
     /// basically like transmuting references of different types. See
-    /// [`mem::transmute`][transmute] for more information on what
+    /// [`mem::transmute`] for more information on what
     /// restrictions apply in this case.
     ///
     /// The raw pointer must point to a block of memory allocated by `alloc`
@@ -1507,7 +1506,6 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
     /// even if the returned `Arc<T>` is never accessed.
     ///
     /// [into_raw]: Arc::into_raw
-    /// [transmute]: core::mem::transmute
     ///
     /// # Examples
     ///
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index faf48ae570f..3c127efb390 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -1406,6 +1406,22 @@ mod impls {
                 _ => unsafe { unreachable_unchecked() },
             }
         }
+
+        #[inline]
+        fn min(self, other: bool) -> bool {
+            self & other
+        }
+
+        #[inline]
+        fn max(self, other: bool) -> bool {
+            self | other
+        }
+
+        #[inline]
+        fn clamp(self, min: bool, max: bool) -> bool {
+            assert!(min <= max);
+            self.max(min).min(max)
+        }
     }
 
     ord_impl! { char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 4082b208c12..163a65c909e 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -20,10 +20,10 @@ use crate::str;
 /// in each pair are borrowed references; the latter are owned
 /// strings.
 ///
-/// Note that this structure is **not** `repr(C)` and is not recommended to be
-/// placed in the signatures of FFI functions. Instead, safe wrappers of FFI
-/// functions may leverage the unsafe [`CStr::from_ptr`] constructor to provide
-/// a safe interface to other consumers.
+/// Note that this structure does **not** have a guaranteed layout (the `repr(transparent)`
+/// notwithstanding) and is not recommended to be placed in the signatures of FFI functions.
+/// Instead, safe wrappers of FFI functions may leverage the unsafe [`CStr::from_ptr`] constructor
+/// to provide a safe interface to other consumers.
 ///
 /// [`CString`]: ../../std/ffi/struct.CString.html
 /// [`String`]: ../../std/string/struct.String.html
@@ -253,7 +253,7 @@ impl CStr {
     /// ```
     ///
     /// [valid]: core::ptr#safety
-    #[inline]
+    #[inline] // inline is necessary for codegen to see strlen.
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_cstr_from_ptr", issue = "113219")]
@@ -280,6 +280,8 @@ impl CStr {
                 len
             }
 
+            // `inline` is necessary for codegen to see strlen.
+            #[inline]
             fn strlen_rt(s: *const c_char) -> usize {
                 extern "C" {
                     /// Provided by libc or compiler_builtins.
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 9ef2c7cde02..676d4f2f38c 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -9,7 +9,7 @@
 //! This includes changes in the stability of the constness.
 //!
 //! In order to make an intrinsic usable at compile-time, one needs to copy the implementation
-//! from <https://github.com/rust-lang/miri/blob/master/src/shims/intrinsics.rs> to
+//! from <https://github.com/rust-lang/miri/blob/master/src/shims/intrinsics> to
 //! <https://github.com/rust-lang/rust/blob/master/compiler/rustc_const_eval/src/interpret/intrinsics.rs> and add a
 //! `#[rustc_const_unstable(feature = "const_such_and_such", issue = "01234")]` to the intrinsic declaration.
 //!
diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs
index 036edbebbf3..ef0a2fd4ec4 100644
--- a/library/core/src/intrinsics/mir.rs
+++ b/library/core/src/intrinsics/mir.rs
@@ -104,17 +104,18 @@
 //! }
 //!
 //! #[custom_mir(dialect = "runtime", phase = "optimized")]
+#![cfg_attr(bootstrap, doc = "#[cfg(any())]")] // disable the following function in doctests when `bootstrap` is set
 //! fn push_and_pop<T>(v: &mut Vec<T>, value: T) {
 //!     mir!(
-//!         let unused;
+//!         let _unused;
 //!         let popped;
 //!
 //!         {
-//!             Call(unused, pop, Vec::push(v, value))
+//!             Call(_unused = Vec::push(v, value), pop)
 //!         }
 //!
 //!         pop = {
-//!             Call(popped, drop, Vec::pop(v))
+//!             Call(popped = Vec::pop(v), drop)
 //!         }
 //!
 //!         drop = {
@@ -275,7 +276,7 @@ define!("mir_return", fn Return() -> BasicBlock);
 define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock);
 define!("mir_unreachable", fn Unreachable() -> BasicBlock);
 define!("mir_drop", fn Drop<T>(place: T, goto: BasicBlock));
-define!("mir_call", fn Call<T>(place: T, goto: BasicBlock, call: T));
+define!("mir_call", fn Call(call: (), goto: BasicBlock));
 define!("mir_storage_live", fn StorageLive<T>(local: T));
 define!("mir_storage_dead", fn StorageDead<T>(local: T));
 define!("mir_deinit", fn Deinit<T>(place: T));
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index ded799160bf..a2729b3743c 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -51,7 +51,7 @@
 #![cfg(not(test))]
 // To run core tests without x.py without ending up with two copies of core, Miri needs to be
 // able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
-// rustc itself never sets the feature, so this line has no affect there.
+// rustc itself never sets the feature, so this line has no effect there.
 #![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
 #![stable(feature = "core", since = "1.6.0")]
 #![doc(
@@ -97,6 +97,8 @@
 #![allow(incomplete_features)]
 #![warn(multiple_supertrait_upcastable)]
 #![cfg_attr(not(bootstrap), allow(internal_features))]
+// Do not check link redundancy on bootstraping phase
+#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))]
 //
 // Library features:
 // tidy-alphabetical-start
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 1199d09b563..1f43520e1b3 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -2126,6 +2126,7 @@ macro_rules! int_impl {
         /// assert_eq!(a.rem_euclid(-b), 3);
         /// assert_eq!((-a).rem_euclid(-b), 1);
         /// ```
+        #[doc(alias = "modulo", alias = "mod")]
         #[stable(feature = "euclidean_division", since = "1.38.0")]
         #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")]
         #[must_use = "this returns the result of the operation, \
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 2136d29255f..81148c7cc51 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -2024,6 +2024,7 @@ macro_rules! uint_impl {
         /// ```
         #[doc = concat!("assert_eq!(7", stringify!($SelfT), ".rem_euclid(4), 3); // or any other integer type")]
         /// ```
+        #[doc(alias = "modulo", alias = "mod")]
         #[stable(feature = "euclidean_division", since = "1.38.0")]
         #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")]
         #[must_use = "this returns the result of the operation, \
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 502f8a75863..ee69d89a4b7 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -55,6 +55,7 @@ impl<T: ?Sized> *const T {
     /// Casts to a pointer of another type.
     #[stable(feature = "ptr_cast", since = "1.38.0")]
     #[rustc_const_stable(feature = "const_ptr_cast", since = "1.38.0")]
+    #[rustc_diagnostic_item = "const_ptr_cast"]
     #[inline(always)]
     pub const fn cast<U>(self) -> *const U {
         self as _
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index d129e1d645f..9dbb3f9d322 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -112,6 +112,7 @@ impl<T: ?Sized> *mut T {
     /// [`cast_mut`]: #method.cast_mut
     #[stable(feature = "ptr_const_cast", since = "1.65.0")]
     #[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")]
+    #[rustc_diagnostic_item = "ptr_cast_const"]
     #[inline(always)]
     pub const fn cast_const(self) -> *const T {
         self as _
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index b641e73f4f8..83d637b685a 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -916,21 +916,34 @@ impl !Send for Punct {}
 #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
 impl !Sync for Punct {}
 
-/// Describes whether a `Punct` is followed immediately by another `Punct` ([`Spacing::Joint`]) or
-/// by a different token or whitespace ([`Spacing::Alone`]).
+/// Indicates whether a `Punct` token can join with the following token
+/// to form a multi-character operator.
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
 pub enum Spacing {
-    /// A `Punct` is not immediately followed by another `Punct`.
-    /// E.g. `+` is `Alone` in `+ =`, `+ident` and `+()`.
-    #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
-    Alone,
-    /// A `Punct` is immediately followed by another `Punct`.
-    /// E.g. `+` is `Joint` in `+=` and `++`.
+    /// A `Punct` token can join with the following token to form a multi-character operator.
+    ///
+    /// In token streams constructed using proc macro interfaces `Joint` punctuation tokens can be
+    /// followed by any other tokens. \
+    /// However, in token streams parsed from source code compiler will only set spacing to `Joint`
+    /// in the following cases:
+    /// - A `Punct` is immediately followed by another `Punct` without a whitespace. \
+    ///   E.g. `+` is `Joint` in `+=` and `++`.
+    /// - A single quote `'` is immediately followed by an identifier without a whitespace. \
+    ///   E.g. `'` is `Joint` in `'lifetime`.
     ///
-    /// Additionally, single quote `'` can join with identifiers to form lifetimes: `'ident`.
+    /// This list may be extended in the future to enable more token combinations.
     #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
     Joint,
+    /// A `Punct` token cannot join with the following token to form a multi-character operator.
+    ///
+    /// `Alone` punctuation tokens can be followed by any other tokens. \
+    /// In token streams parsed from source code compiler will set spacing to `Alone` in all cases
+    /// not covered by the conditions for `Joint` above. \
+    /// E.g. `+` is `Alone` in `+ =`, `+ident` and `+()`.
+    /// In particular, token not followed by anything  will also be marked as `Alone`.
+    #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
+    Alone,
 }
 
 impl Punct {
@@ -962,10 +975,9 @@ impl Punct {
         self.0.ch as char
     }
 
-    /// Returns the spacing of this punctuation character, indicating whether it's immediately
-    /// followed by another `Punct` in the token stream, so they can potentially be combined into
-    /// a multi-character operator (`Joint`), or it's followed by some other token or whitespace
-    /// (`Alone`) so the operator has certainly ended.
+    /// Returns the spacing of this punctuation character, indicating whether it can be potentially
+    /// combined into a multi-character operator with the following token (`Joint`), or the operator
+    /// has certainly ended (`Alone`).
     #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
     pub fn spacing(&self) -> Spacing {
         if self.0.joint { Spacing::Joint } else { Spacing::Alone }
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index a083b65604d..be173a7ace6 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -49,12 +49,14 @@ use crate::sys;
 /// ```
 ///
 /// In other words, if two keys are equal, their hashes must be equal.
+/// Violating this property is a logic error.
 ///
-/// It is a logic error for a key to be modified in such a way that the key's
+/// It is also a logic error for a key to be modified in such a way that the key's
 /// hash, as determined by the [`Hash`] trait, or its equality, as determined by
 /// the [`Eq`] trait, changes while it is in the map. This is normally only
 /// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
-/// The behavior resulting from such a logic error is not specified, but will
+///
+/// The behavior resulting from either logic error is not specified, but will
 /// be encapsulated to the `HashMap` that observed the logic error and not
 /// result in undefined behavior. This could include panics, incorrect results,
 /// aborts, memory leaks, and non-termination.
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index 959403e1644..6d85b26af5f 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -24,13 +24,14 @@ use super::map::{map_try_reserve_error, RandomState};
 /// ```
 ///
 /// In other words, if two keys are equal, their hashes must be equal.
+/// Violating this property is a logic error.
 ///
-///
-/// It is a logic error for a key to be modified in such a way that the key's
+/// It is also a logic error for a key to be modified in such a way that the key's
 /// hash, as determined by the [`Hash`] trait, or its equality, as determined by
 /// the [`Eq`] trait, changes while it is in the map. This is normally only
 /// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
-/// The behavior resulting from such a logic error is not specified, but will
+///
+/// The behavior resulting from either logic error is not specified, but will
 /// be encapsulated to the `HashSet` that observed the logic error and not
 /// result in undefined behavior. This could include panics, incorrect results,
 /// aborts, memory leaks, and non-termination.
diff --git a/library/std/src/error.rs b/library/std/src/error.rs
index 7bc3af1793e..375ff2d2450 100644
--- a/library/std/src/error.rs
+++ b/library/std/src/error.rs
@@ -10,7 +10,7 @@ use crate::fmt::{self, Write};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::error::Error;
 #[unstable(feature = "error_generic_member_access", issue = "99301")]
-pub use core::error::{request_ref, Request};
+pub use core::error::{request_ref, request_value, Request};
 
 mod private {
     // This is a hack to prevent `type_id` from being overridden by `Error`
diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs
index a53b8535213..a659b552f47 100644
--- a/library/std/src/f32.rs
+++ b/library/std/src/f32.rs
@@ -61,6 +61,7 @@ impl f32 {
     /// assert_eq!(f.ceil(), 4.0);
     /// assert_eq!(g.ceil(), 4.0);
     /// ```
+    #[doc(alias = "ceiling")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -135,6 +136,7 @@ impl f32 {
     /// assert_eq!(g.trunc(), 3.0);
     /// assert_eq!(h.trunc(), -3.0);
     /// ```
+    #[doc(alias = "truncate")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -321,6 +323,7 @@ impl f32 {
     /// // limitation due to round-off error
     /// assert!((-f32::EPSILON).rem_euclid(3.0) != 0.0);
     /// ```
+    #[doc(alias = "modulo", alias = "mod")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
@@ -672,6 +675,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[doc(alias = "arcsin")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -694,6 +698,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[doc(alias = "arccos")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -715,6 +720,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[doc(alias = "arctan")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -772,6 +778,7 @@ impl f32 {
     /// assert!(abs_difference_0 <= f32::EPSILON);
     /// assert!(abs_difference_1 <= f32::EPSILON);
     /// ```
+    #[doc(alias = "sincos")]
     #[rustc_allow_incoherent_impl]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -904,6 +911,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[doc(alias = "arcsinh")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -926,6 +934,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[doc(alias = "arccosh")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -950,6 +959,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= 1e-5);
     /// ```
+    #[doc(alias = "arctanh")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs
index a1cec22c97a..721e1fb754e 100644
--- a/library/std/src/f64.rs
+++ b/library/std/src/f64.rs
@@ -61,6 +61,7 @@ impl f64 {
     /// assert_eq!(f.ceil(), 4.0);
     /// assert_eq!(g.ceil(), 4.0);
     /// ```
+    #[doc(alias = "ceiling")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -135,6 +136,7 @@ impl f64 {
     /// assert_eq!(g.trunc(), 3.0);
     /// assert_eq!(h.trunc(), -3.0);
     /// ```
+    #[doc(alias = "truncate")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -321,6 +323,7 @@ impl f64 {
     /// // limitation due to round-off error
     /// assert!((-f64::EPSILON).rem_euclid(3.0) != 0.0);
     /// ```
+    #[doc(alias = "modulo", alias = "mod")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
@@ -672,6 +675,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[doc(alias = "arcsin")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -694,6 +698,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[doc(alias = "arccos")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -715,6 +720,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[doc(alias = "arctan")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -772,6 +778,7 @@ impl f64 {
     /// assert!(abs_difference_0 < 1e-10);
     /// assert!(abs_difference_1 < 1e-10);
     /// ```
+    #[doc(alias = "sincos")]
     #[rustc_allow_incoherent_impl]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -904,6 +911,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1.0e-10);
     /// ```
+    #[doc(alias = "arcsinh")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -926,6 +934,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1.0e-10);
     /// ```
+    #[doc(alias = "arccosh")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -950,6 +959,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1.0e-10);
     /// ```
+    #[doc(alias = "arctanh")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 5c1d2d8f46c..71d91f21362 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -1425,9 +1425,9 @@ pub trait Write {
     ///
     /// If this method consumed `n > 0` bytes of `buf` it must return [`Ok(n)`].
     /// If the return value is `Ok(n)` then `n` must satisfy `n <= buf.len()`.
-    /// Unless `buf` is empty, this function shouldn’t return `Ok(0)` since the
-    /// caller may interpret that as an error.  To indicate lack of space,
-    /// implementors should return [`ErrorKind::StorageFull`] error instead.
+    /// A return value of `Ok(0)` typically means that the underlying object is
+    /// no longer able to accept bytes and will likely not be able to in the
+    /// future as well, or that the buffer provided is empty.
     ///
     /// # Errors
     ///
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index c07aa5cd91f..58684ffe500 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -190,7 +190,7 @@
 
 // To run std tests without x.py without ending up with two copies of std, Miri needs to be
 // able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
-// rustc itself never sets the feature, so this line has no affect there.
+// rustc itself never sets the feature, so this line has no effect there.
 #![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
 // miri-test-libstd also prefers to make std use the sysroot versions of the dependencies.
 #![cfg_attr(feature = "miri-test-libstd", feature(rustc_private))]
@@ -223,6 +223,7 @@
 #![cfg_attr(not(bootstrap), allow(internal_features))]
 #![deny(rustc::existing_doc_keyword)]
 #![deny(fuzzy_provenance_casts)]
+#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))]
 // Ensure that std can be linked against panic_abort despite compiled with `-C panic=unwind`
 #![deny(ffi_unwind_calls)]
 // std may use features in a platform-specific way
diff --git a/library/std/src/sync/mpsc/mod.rs b/library/std/src/sync/mpsc/mod.rs
index c00134c8b95..f92bb1a4b1f 100644
--- a/library/std/src/sync/mpsc/mod.rs
+++ b/library/std/src/sync/mpsc/mod.rs
@@ -303,12 +303,11 @@ pub struct IntoIter<T> {
     rx: Receiver<T>,
 }
 
-/// The sending-half of Rust's asynchronous [`channel`] type. This half can only be
-/// owned by one thread, but it can be cloned to send to other threads.
+/// The sending-half of Rust's asynchronous [`channel`] type.
 ///
 /// Messages can be sent through this channel with [`send`].
 ///
-/// Note: all senders (the original and the clones) need to be dropped for the receiver
+/// Note: all senders (the original and its clones) need to be dropped for the receiver
 /// to stop blocking to receive messages with [`Receiver::recv`].
 ///
 /// [`send`]: Sender::send
diff --git a/library/std/src/sys/solid/os.rs b/library/std/src/sys/solid/os.rs
index 717c08434a8..9f4e66d628b 100644
--- a/library/std/src/sys/solid/os.rs
+++ b/library/std/src/sys/solid/os.rs
@@ -81,6 +81,10 @@ pub fn current_exe() -> io::Result<PathBuf> {
 
 static ENV_LOCK: RwLock<()> = RwLock::new(());
 
+pub fn env_read_lock() -> impl Drop {
+    ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner)
+}
+
 pub struct Env {
     iter: vec::IntoIter<(OsString, OsString)>,
 }
@@ -134,7 +138,7 @@ pub fn env() -> Env {
     }
 
     unsafe {
-        let _guard = ENV_LOCK.read();
+        let _guard = env_read_lock();
         let mut result = Vec::new();
         if !environ.is_null() {
             while !(*environ).is_null() {
@@ -168,17 +172,21 @@ pub fn env() -> Env {
 pub fn getenv(k: &OsStr) -> Option<OsString> {
     // environment variables with a nul byte can't be set, so their value is
     // always None as well
-    let s = run_with_cstr(k.as_bytes(), |k| {
-        let _guard = ENV_LOCK.read();
-        Ok(unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char)
-    })
-    .ok()?;
+    run_with_cstr(k.as_bytes(), |k| {
+        let _guard = env_read_lock();
+        let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
 
-    if s.is_null() {
-        None
-    } else {
-        Some(OsStringExt::from_vec(unsafe { CStr::from_ptr(s) }.to_bytes().to_vec()))
-    }
+        if v.is_null() {
+            Ok(None)
+        } else {
+            // SAFETY: `v` cannot be mutated while executing this line since we've a read lock
+            let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
+
+            Ok(Some(OsStringExt::from_vec(bytes)))
+        }
+    })
+    .ok()
+    .flatten()
 }
 
 pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index 215f63d04f7..57e1a36dace 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -594,16 +594,21 @@ pub fn env() -> Env {
 pub fn getenv(k: &OsStr) -> Option<OsString> {
     // environment variables with a nul byte can't be set, so their value is
     // always None as well
-    let s = run_with_cstr(k.as_bytes(), |k| {
+    run_with_cstr(k.as_bytes(), |k| {
         let _guard = env_read_lock();
-        Ok(unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char)
+        let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
+
+        if v.is_null() {
+            Ok(None)
+        } else {
+            // SAFETY: `v` cannot be mutated while executing this line since we've a read lock
+            let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
+
+            Ok(Some(OsStringExt::from_vec(bytes)))
+        }
     })
-    .ok()?;
-    if s.is_null() {
-        None
-    } else {
-        Some(OsStringExt::from_vec(unsafe { CStr::from_ptr(s) }.to_bytes().to_vec()))
-    }
+    .ok()
+    .flatten()
 }
 
 pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
diff --git a/library/std/src/sys/wasi/os.rs b/library/std/src/sys/wasi/os.rs
index e0de284c5e2..d53bddd8e9d 100644
--- a/library/std/src/sys/wasi/os.rs
+++ b/library/std/src/sys/wasi/os.rs
@@ -225,16 +225,23 @@ pub fn env() -> Env {
 }
 
 pub fn getenv(k: &OsStr) -> Option<OsString> {
-    let s = run_with_cstr(k.as_bytes(), |k| unsafe {
+    // environment variables with a nul byte can't be set, so their value is
+    // always None as well
+    run_with_cstr(k.as_bytes(), |k| {
         let _guard = env_read_lock();
-        Ok(libc::getenv(k.as_ptr()) as *const libc::c_char)
+        let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
+
+        if v.is_null() {
+            Ok(None)
+        } else {
+            // SAFETY: `v` cannot be mutated while executing this line since we've a read lock
+            let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
+
+            Ok(Some(OsStringExt::from_vec(bytes)))
+        }
     })
-    .ok()?;
-    if s.is_null() {
-        None
-    } else {
-        Some(OsStringExt::from_vec(unsafe { CStr::from_ptr(s) }.to_bytes().to_vec()))
-    }
+    .ok()
+    .flatten()
 }
 
 pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
diff --git a/library/std/src/sys/windows/os.rs b/library/std/src/sys/windows/os.rs
index 2329426ad1d..58afca088ef 100644
--- a/library/std/src/sys/windows/os.rs
+++ b/library/std/src/sys/windows/os.rs
@@ -25,10 +25,6 @@ pub fn errno() -> i32 {
 
 /// Gets a detailed string description for the given error number.
 pub fn error_string(mut errnum: i32) -> String {
-    // This value is calculated from the macro
-    // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT)
-    let langId = 0x0800 as c::DWORD;
-
     let mut buf = [0 as c::WCHAR; 2048];
 
     unsafe {
@@ -56,13 +52,13 @@ pub fn error_string(mut errnum: i32) -> String {
             flags | c::FORMAT_MESSAGE_FROM_SYSTEM | c::FORMAT_MESSAGE_IGNORE_INSERTS,
             module,
             errnum as c::DWORD,
-            langId,
+            0,
             buf.as_mut_ptr(),
             buf.len() as c::DWORD,
             ptr::null(),
         ) as usize;
         if res == 0 {
-            // Sometimes FormatMessageW can fail e.g., system doesn't like langId,
+            // Sometimes FormatMessageW can fail e.g., system doesn't like 0 as langId,
             let fm_err = errno();
             return format!("OS Error {errnum} (FormatMessageW() returned error {fm_err})");
         }
diff --git a/library/std/src/sys_common/thread_parking/id.rs b/library/std/src/sys_common/thread_parking/id.rs
index 15042fc3bee..04667439660 100644
--- a/library/std/src/sys_common/thread_parking/id.rs
+++ b/library/std/src/sys_common/thread_parking/id.rs
@@ -56,18 +56,14 @@ impl Parker {
         self.init_tid();
 
         // Changes NOTIFIED to EMPTY and EMPTY to PARKED.
-        let mut state = self.state.fetch_sub(1, Acquire).wrapping_sub(1);
-        if state == PARKED {
+        let state = self.state.fetch_sub(1, Acquire);
+        if state == EMPTY {
             // Loop to guard against spurious wakeups.
-            while state == PARKED {
+            // The state must be reset with acquire ordering to ensure that all
+            // calls to `unpark` synchronize with this thread.
+            while self.state.compare_exchange(NOTIFIED, EMPTY, Acquire, Relaxed).is_err() {
                 park(self.state.as_ptr().addr());
-                state = self.state.load(Acquire);
             }
-
-            // Since the state change has already been observed with acquire
-            // ordering, the state can be reset with a relaxed store instead
-            // of a swap.
-            self.state.store(EMPTY, Relaxed);
         }
     }
 
@@ -78,8 +74,7 @@ impl Parker {
         if state == PARKED {
             park_timeout(dur, self.state.as_ptr().addr());
             // Swap to ensure that we observe all state changes with acquire
-            // ordering, even if the state has been changed after the timeout
-            // occurred.
+            // ordering.
             self.state.swap(EMPTY, Acquire);
         }
     }
diff --git a/library/std/tests/env.rs b/library/std/tests/env.rs
index 96b4f372b8b..a1ca85c2145 100644
--- a/library/std/tests/env.rs
+++ b/library/std/tests/env.rs
@@ -5,6 +5,7 @@ use rand::distributions::{Alphanumeric, DistString};
 
 mod common;
 use common::test_rng;
+use std::thread;
 
 #[track_caller]
 fn make_rand_name() -> OsString {
@@ -140,3 +141,22 @@ fn env_home_dir() {
         }
     }
 }
+
+#[test] // miri shouldn't detect any data race in this fn
+#[cfg_attr(any(not(miri), target_os = "emscripten"), ignore)]
+fn test_env_get_set_multithreaded() {
+    let getter = thread::spawn(|| {
+        for _ in 0..100 {
+            let _ = var_os("foo");
+        }
+    });
+
+    let setter = thread::spawn(|| {
+        for _ in 0..100 {
+            set_var("foo", "bar");
+        }
+    });
+
+    let _ = getter.join();
+    let _ = setter.join();
+}
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index 2cc0bfd9db9..89b82d59d31 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -504,18 +504,6 @@ jobs:
               NO_OVERFLOW_CHECKS: 1
             <<: *job-macos-xl
 
-          - name: dist-x86_64-apple-alt
-            env:
-              SCRIPT: ./x.py dist bootstrap --include-default-paths
-              RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc --set llvm.ninja=false
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.7
-              SELECT_XCODE: /Applications/Xcode_13.4.1.app
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              NO_OVERFLOW_CHECKS: 1
-            <<: *job-macos-xl
-
           - name: x86_64-apple-1
             env: &env-x86_64-apple-tests
               SCRIPT: ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc --skip tests/run-make-fulldeps
diff --git a/src/doc/rustc/book.toml b/src/doc/rustc/book.toml
index 14ae1a7207a..167aece0ed6 100644
--- a/src/doc/rustc/book.toml
+++ b/src/doc/rustc/book.toml
@@ -7,5 +7,8 @@ title = "The rustc book"
 git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/rustc"
 edit-url-template = "https://github.com/rust-lang/rust/edit/master/src/doc/rustc/{path}"
 
+[output.html.search]
+use-boolean-and = true
+
 [output.html.playground]
 runnable = false
diff --git a/src/doc/rustdoc/src/lints.md b/src/doc/rustdoc/src/lints.md
index fd57b079644..f15e6e451e7 100644
--- a/src/doc/rustdoc/src/lints.md
+++ b/src/doc/rustdoc/src/lints.md
@@ -412,3 +412,37 @@ help: if you meant to use a literal backtick, escape it
 
 warning: 1 warning emitted
 ```
+
+## `redundant_explicit_links`
+
+This lint is **warned by default**. It detects explicit links that are same
+as computed automatic links.
+This usually means the explicit links is removeable. For example:
+
+```rust
+#![warn(rustdoc::redundant_explicit_links)] // note: unnecessary - warns by default.
+
+/// add takes 2 [`usize`](usize) and performs addition
+/// on them, then returns result.
+pub fn add(left: usize, right: usize) -> usize {
+    left + right
+}
+```
+
+Which will give:
+
+```text
+error: redundant explicit rustdoc link
+  --> src/lib.rs:3:27
+   |
+3  | /// add takes 2 [`usize`](usize) and performs addition
+   |                           ^^^^^
+   |
+   = note: Explicit link does not affect the original link
+note: the lint level is defined here
+  --> src/lib.rs:1:9
+   |
+1  | #![deny(rustdoc::redundant_explicit_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: Remove explicit link instead
+```
diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md
index 1f3d472c3aa..9e20662fff3 100644
--- a/src/doc/unstable-book/src/language-features/lang-items.md
+++ b/src/doc/unstable-book/src/language-features/lang-items.md
@@ -9,26 +9,60 @@ functionality that isn't hard-coded into the language, but is
 implemented in libraries, with a special marker to tell the compiler
 it exists. The marker is the attribute `#[lang = "..."]` and there are
 various different values of `...`, i.e. various different 'lang
-items'.
+items'. Most of them can only be defined once.
 
-For example, `Box` pointers require a lang item for allocation.
-A freestanding program that uses the `Box`
-sugar for dynamic allocations via `malloc` and `free`:
+Lang items are loaded lazily by the compiler; e.g. if one never uses `Box`
+then there is no need to define a function for `exchange_malloc`.
+`rustc` will emit an error when an item is needed but not found in the current
+crate or any that it depends on.
+
+Some features provided by lang items:
+
+- overloadable operators via traits: the traits corresponding to the
+  `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all
+  marked with lang items; those specific four are `eq`, `partial_ord`,
+  `deref`/`deref_mut`, and `add` respectively.
+- panicking: the `panic` and `panic_impl` lang items, among others.
+- stack unwinding: the lang item `eh_personality` is a function used by the
+  failure mechanisms of the compiler. This is often mapped to GCC's personality
+  function (see the [`std` implementation][personality] for more information),
+  but programs which don't trigger a panic can be assured that this function is
+  never called. Additionally, a `eh_catch_typeinfo` static is needed for certain
+  targets which implement Rust panics on top of C++ exceptions.
+- the traits in `core::marker` used to indicate types of
+  various kinds; e.g. lang items `sized`, `sync` and `copy`.
+- memory allocation, see below.
+
+Most lang items are defined by `core`, but if you're trying to build
+an executable without the `std` crate, you might run into the need
+for lang item definitions.
+
+[personality]: https://github.com/rust-lang/rust/blob/master/library/std/src/personality/gcc.rs
+
+## Example: Implementing a `Box`
+
+`Box` pointers require two lang items: one for the type itself and one for
+allocation. A freestanding program that uses the `Box` sugar for dynamic
+allocations via `malloc` and `free`:
 
 ```rust,ignore (libc-is-finicky)
-#![feature(lang_items, start, libc, core_intrinsics, rustc_private, rustc_attrs)]
+#![feature(lang_items, start, core_intrinsics, rustc_private, panic_unwind, rustc_attrs)]
 #![allow(internal_features)]
 #![no_std]
+
+extern crate libc;
+extern crate unwind;
+
+use core::ffi::c_void;
 use core::intrinsics;
 use core::panic::PanicInfo;
 use core::ptr::NonNull;
 
-extern crate libc;
-
+pub struct Global; // the global allocator
 struct Unique<T>(NonNull<T>);
 
 #[lang = "owned_box"]
-pub struct Box<T>(Unique<T>);
+pub struct Box<T, A = Global>(Unique<T>, A);
 
 impl<T> Box<T> {
     pub fn new(x: T) -> Self {
@@ -37,24 +71,26 @@ impl<T> Box<T> {
     }
 }
 
+impl<T, A> Drop for Box<T, A> {
+    fn drop(&mut self) {
+        unsafe {
+            libc::free(self.0.0.as_ptr() as *mut c_void);
+        }
+    }
+}
+
 #[lang = "exchange_malloc"]
 unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
-    let p = libc::malloc(size as libc::size_t) as *mut u8;
+    let p = libc::malloc(size) as *mut u8;
 
     // Check if `malloc` failed:
-    if p as usize == 0 {
+    if p.is_null() {
         intrinsics::abort();
     }
 
     p
 }
 
-impl<T> Drop for Box<T> {
-    fn drop(&mut self) {
-      libc::free(self.0.0.0 as *mut libc::c_void)
-    }
-}
-
 #[start]
 fn main(_argc: isize, _argv: *const *const u8) -> isize {
     let _x = Box::new(1);
@@ -62,247 +98,18 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
     0
 }
 
-#[lang = "eh_personality"] extern fn rust_eh_personality() {}
-#[lang = "panic_impl"] extern fn rust_begin_panic(_info: &PanicInfo) -> ! { intrinsics::abort() }
-#[no_mangle] pub extern fn rust_eh_register_frames () {}
-#[no_mangle] pub extern fn rust_eh_unregister_frames () {}
-```
-
-Note the use of `abort`: the `exchange_malloc` lang item is assumed to
-return a valid pointer, and so needs to do the check internally.
-
-Other features provided by lang items include:
-
-- overloadable operators via traits: the traits corresponding to the
-  `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all
-  marked with lang items; those specific four are `eq`, `ord`,
-  `deref`, and `add` respectively.
-- stack unwinding and general failure; the `eh_personality`,
-  `panic` and `panic_bounds_check` lang items.
-- the traits in `std::marker` used to indicate types of
-  various kinds; lang items `send`, `sync` and `copy`.
-- the marker types and variance indicators found in
-  `std::marker`; lang items `covariant_type`,
-  `contravariant_lifetime`, etc.
-
-Lang items are loaded lazily by the compiler; e.g. if one never uses
-`Box` then there is no need to define a function for `exchange_malloc`.
-`rustc` will emit an error when an item is needed
-but not found in the current crate or any that it depends on.
-
-Most lang items are defined by `libcore`, but if you're trying to build
-an executable without the standard library, you'll run into the need
-for lang items. The rest of this page focuses on this use-case, even though
-lang items are a bit broader than that.
-
-### Using libc
-
-In order to build a `#[no_std]` executable we will need libc as a dependency.
-We can specify this using our `Cargo.toml` file:
-
-```toml
-[dependencies]
-libc = { version = "0.2.14", default-features = false }
-```
-
-Note that the default features have been disabled. This is a critical step -
-**the default features of libc include the standard library and so must be
-disabled.**
-
-### Writing an executable without stdlib
-
-Controlling the entry point is possible in two ways: the `#[start]` attribute,
-or overriding the default shim for the C `main` function with your own.
-
-The function marked `#[start]` is passed the command line parameters
-in the same format as C:
-
-```rust,ignore (libc-is-finicky)
-#![feature(lang_items, core_intrinsics, rustc_private)]
-#![feature(start)]
-#![allow(internal_features)]
-#![no_std]
-use core::intrinsics;
-use core::panic::PanicInfo;
-
-// Pull in the system libc library for what crt0.o likely requires.
-extern crate libc;
-
-// Entry point for this program.
-#[start]
-fn start(_argc: isize, _argv: *const *const u8) -> isize {
-    0
-}
-
-// These functions are used by the compiler, but not
-// for a bare-bones hello world. These are normally
-// provided by libstd.
-#[lang = "eh_personality"]
-#[no_mangle]
-pub extern fn rust_eh_personality() {
-}
-
-#[lang = "panic_impl"]
-#[no_mangle]
-pub extern fn rust_begin_panic(info: &PanicInfo) -> ! {
-    unsafe { intrinsics::abort() }
-}
-```
-
-To override the compiler-inserted `main` shim, one has to disable it
-with `#![no_main]` and then create the appropriate symbol with the
-correct ABI and the correct name, which requires overriding the
-compiler's name mangling too:
-
-```rust,ignore (libc-is-finicky)
-#![feature(lang_items, core_intrinsics, rustc_private)]
-#![feature(start)]
-#![allow(internal_features)]
-#![no_std]
-#![no_main]
-use core::intrinsics;
-use core::panic::PanicInfo;
-
-// Pull in the system libc library for what crt0.o likely requires.
-extern crate libc;
-
-// Entry point for this program.
-#[no_mangle] // ensure that this symbol is called `main` in the output
-pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 {
-    0
-}
-
-// These functions are used by the compiler, but not
-// for a bare-bones hello world. These are normally
-// provided by libstd.
 #[lang = "eh_personality"]
-#[no_mangle]
-pub extern fn rust_eh_personality() {
-}
+fn rust_eh_personality() {}
 
-#[lang = "panic_impl"]
-#[no_mangle]
-pub extern fn rust_begin_panic(info: &PanicInfo) -> ! {
-    unsafe { intrinsics::abort() }
-}
+#[panic_handler]
+fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() }
 ```
 
-In many cases, you may need to manually link to the `compiler_builtins` crate
-when building a `no_std` binary. You may observe this via linker error messages
-such as "```undefined reference to `__rust_probestack'```".
-
-## More about the language items
-
-The compiler currently makes a few assumptions about symbols which are
-available in the executable to call. Normally these functions are provided by
-the standard library, but without it you must define your own. These symbols
-are called "language items", and they each have an internal name, and then a
-signature that an implementation must conform to.
-
-The first of these functions, `rust_eh_personality`, is used by the failure
-mechanisms of the compiler. This is often mapped to GCC's personality function
-(see the [libstd implementation][unwind] for more information), but crates
-which do not trigger a panic can be assured that this function is never
-called. The language item's name is `eh_personality`.
-
-[unwind]: https://github.com/rust-lang/rust/blob/master/library/panic_unwind/src/gcc.rs
-
-The second function, `rust_begin_panic`, is also used by the failure mechanisms of the
-compiler. When a panic happens, this controls the message that's displayed on
-the screen. While the language item's name is `panic_impl`, the symbol name is
-`rust_begin_panic`.
-
-Finally, a `eh_catch_typeinfo` static is needed for certain targets which
-implement Rust panics on top of C++ exceptions.
+Note the use of `abort`: the `exchange_malloc` lang item is assumed to
+return a valid pointer, and so needs to do the check internally.
 
 ## List of all language items
 
-This is a list of all language items in Rust along with where they are located in
-the source code.
+An up-to-date list of all language items can be found [here] in the compiler code.
 
-- Primitives
-  - `i8`: `libcore/num/mod.rs`
-  - `i16`: `libcore/num/mod.rs`
-  - `i32`: `libcore/num/mod.rs`
-  - `i64`: `libcore/num/mod.rs`
-  - `i128`: `libcore/num/mod.rs`
-  - `isize`: `libcore/num/mod.rs`
-  - `u8`: `libcore/num/mod.rs`
-  - `u16`: `libcore/num/mod.rs`
-  - `u32`: `libcore/num/mod.rs`
-  - `u64`: `libcore/num/mod.rs`
-  - `u128`: `libcore/num/mod.rs`
-  - `usize`: `libcore/num/mod.rs`
-  - `f32`: `libstd/f32.rs`
-  - `f64`: `libstd/f64.rs`
-  - `char`: `libcore/char.rs`
-  - `slice`: `liballoc/slice.rs`
-  - `str`: `liballoc/str.rs`
-  - `const_ptr`: `libcore/ptr.rs`
-  - `mut_ptr`: `libcore/ptr.rs`
-  - `unsafe_cell`: `libcore/cell.rs`
-- Runtime
-  - `start`: `libstd/rt.rs`
-  - `eh_personality`: `libpanic_unwind/emcc.rs` (EMCC)
-  - `eh_personality`: `libpanic_unwind/gcc.rs` (GNU)
-  - `eh_personality`: `libpanic_unwind/seh.rs` (SEH)
-  - `eh_catch_typeinfo`: `libpanic_unwind/emcc.rs` (EMCC)
-  - `panic`: `libcore/panicking.rs`
-  - `panic_bounds_check`: `libcore/panicking.rs`
-  - `panic_impl`: `libcore/panicking.rs`
-  - `panic_impl`: `libstd/panicking.rs`
-- Allocations
-  - `owned_box`: `liballoc/boxed.rs`
-  - `exchange_malloc`: `liballoc/heap.rs`
-- Operands
-  - `not`: `libcore/ops/bit.rs`
-  - `bitand`: `libcore/ops/bit.rs`
-  - `bitor`: `libcore/ops/bit.rs`
-  - `bitxor`: `libcore/ops/bit.rs`
-  - `shl`: `libcore/ops/bit.rs`
-  - `shr`: `libcore/ops/bit.rs`
-  - `bitand_assign`: `libcore/ops/bit.rs`
-  - `bitor_assign`: `libcore/ops/bit.rs`
-  - `bitxor_assign`: `libcore/ops/bit.rs`
-  - `shl_assign`: `libcore/ops/bit.rs`
-  - `shr_assign`: `libcore/ops/bit.rs`
-  - `deref`: `libcore/ops/deref.rs`
-  - `deref_mut`: `libcore/ops/deref.rs`
-  - `index`: `libcore/ops/index.rs`
-  - `index_mut`: `libcore/ops/index.rs`
-  - `add`: `libcore/ops/arith.rs`
-  - `sub`: `libcore/ops/arith.rs`
-  - `mul`: `libcore/ops/arith.rs`
-  - `div`: `libcore/ops/arith.rs`
-  - `rem`: `libcore/ops/arith.rs`
-  - `neg`: `libcore/ops/arith.rs`
-  - `add_assign`: `libcore/ops/arith.rs`
-  - `sub_assign`: `libcore/ops/arith.rs`
-  - `mul_assign`: `libcore/ops/arith.rs`
-  - `div_assign`: `libcore/ops/arith.rs`
-  - `rem_assign`: `libcore/ops/arith.rs`
-  - `eq`: `libcore/cmp.rs`
-  - `ord`: `libcore/cmp.rs`
-- Functions
-  - `fn`: `libcore/ops/function.rs`
-  - `fn_mut`: `libcore/ops/function.rs`
-  - `fn_once`: `libcore/ops/function.rs`
-  - `generator_state`: `libcore/ops/generator.rs`
-  - `generator`: `libcore/ops/generator.rs`
-- Other
-  - `coerce_unsized`: `libcore/ops/unsize.rs`
-  - `drop`: `libcore/ops/drop.rs`
-  - `drop_in_place`: `libcore/ptr.rs`
-  - `clone`: `libcore/clone.rs`
-  - `copy`: `libcore/marker.rs`
-  - `send`: `libcore/marker.rs`
-  - `sized`: `libcore/marker.rs`
-  - `unsize`: `libcore/marker.rs`
-  - `sync`: `libcore/marker.rs`
-  - `phantom_data`: `libcore/marker.rs`
-  - `discriminant_kind`: `libcore/marker.rs`
-  - `freeze`: `libcore/marker.rs`
-  - `debug_trait`: `libcore/fmt/mod.rs`
-  - `non_zero`: `libcore/nonzero.rs`
-  - `arc`: `liballoc/sync.rs`
-  - `rc`: `liballoc/rc.rs`
+[here]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_hir/src/lang_items.rs
diff --git a/src/doc/unstable-book/src/language-features/start.md b/src/doc/unstable-book/src/language-features/start.md
new file mode 100644
index 00000000000..09e4875a2e4
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/start.md
@@ -0,0 +1,59 @@
+# `start`
+
+The tracking issue for this feature is: [#29633]
+
+[#29633]: https://github.com/rust-lang/rust/issues/29633
+
+------------------------
+
+Allows you to mark a function as the entry point of the executable, which is
+necessary in `#![no_std]` environments.
+
+The function marked `#[start]` is passed the command line parameters in the same
+format as the C main function (aside from the integer types being used).
+It has to be non-generic and have the following signature:
+
+```rust,ignore (only-for-syntax-highlight)
+# let _:
+fn(isize, *const *const u8) -> isize
+# ;
+```
+
+This feature should not be confused with the `start` *lang item* which is
+defined by the `std` crate and is written `#[lang = "start"]`.
+
+## Usage together with the `std` crate
+
+`#[start]` can be used in combination with the `std` crate, in which case the
+normal `main` function (which would get called from the `std` crate) won't be
+used as an entry point.
+The initialization code in `std` will be skipped this way.
+
+Example:
+
+```rust
+#![feature(start)]
+
+#[start]
+fn start(_argc: isize, _argv: *const *const u8) -> isize {
+    0
+}
+```
+
+Unwinding the stack past the `#[start]` function is currently considered
+Undefined Behavior (for any unwinding implementation):
+
+```rust,ignore (UB)
+#![feature(start)]
+
+#[start]
+fn start(_argc: isize, _argv: *const *const u8) -> isize {
+    std::panic::catch_unwind(|| {
+        panic!(); // panic safely gets caught or safely aborts execution
+    });
+
+    panic!(); // UB!
+
+    0
+}
+```
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 68d636b360a..a06f31a9329 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -46,7 +46,7 @@ where
         let tcx = self.cx.tcx;
         let trait_ref = ty::Binder::dummy(ty::TraitRef::new(tcx, trait_def_id, [ty]));
         if !self.cx.generated_synthetics.insert((ty, trait_def_id)) {
-            debug!("get_auto_trait_impl_for({:?}): already generated, aborting", trait_ref);
+            debug!("get_auto_trait_impl_for({trait_ref:?}): already generated, aborting");
             return None;
         }
 
@@ -140,7 +140,7 @@ where
         let ty = tcx.type_of(item_def_id).instantiate_identity();
         let f = auto_trait::AutoTraitFinder::new(tcx);
 
-        debug!("get_auto_trait_impls({:?})", ty);
+        debug!("get_auto_trait_impls({ty:?})");
         let auto_traits: Vec<_> = self.cx.auto_traits.to_vec();
         let mut auto_traits: Vec<Item> = auto_traits
             .into_iter()
@@ -163,9 +163,9 @@ where
     fn get_lifetime(region: Region<'_>, names_map: &FxHashMap<Symbol, Lifetime>) -> Lifetime {
         region_name(region)
             .map(|name| {
-                names_map.get(&name).unwrap_or_else(|| {
-                    panic!("Missing lifetime with name {:?} for {:?}", name.as_str(), region)
-                })
+                names_map
+                    .get(&name)
+                    .unwrap_or_else(|| panic!("Missing lifetime with name {name:?} for {region:?}"))
             })
             .unwrap_or(&Lifetime::statik())
             .clone()
@@ -372,7 +372,7 @@ where
 
                     let output = output.as_ref().cloned().map(Box::new);
                     if old_output.is_some() && old_output != output {
-                        panic!("Output mismatch for {:?} {:?} {:?}", ty, old_output, output);
+                        panic!("Output mismatch for {ty:?} {old_output:?} {output:?}");
                     }
 
                     let new_params = GenericArgs::Parenthesized { inputs: old_input, output };
@@ -462,7 +462,7 @@ where
         );
         let mut generic_params = raw_generics.params;
 
-        debug!("param_env_to_generics({:?}): generic_params={:?}", item_def_id, generic_params);
+        debug!("param_env_to_generics({item_def_id:?}): generic_params={generic_params:?}");
 
         let mut has_sized = FxHashSet::default();
         let mut ty_to_bounds: FxHashMap<_, FxHashSet<_>> = Default::default();
@@ -623,7 +623,7 @@ where
                             // loop
                             ty_to_traits.entry(ty.clone()).or_default().insert(trait_.clone());
                         }
-                        _ => panic!("Unexpected LHS {:?} for {:?}", lhs, item_def_id),
+                        _ => panic!("Unexpected LHS {lhs:?} for {item_def_id:?}"),
                     }
                 }
             };
@@ -710,7 +710,7 @@ where
     /// involved (impls rarely have more than a few bounds) means that it
     /// shouldn't matter in practice.
     fn unstable_debug_sort<T: Debug>(&self, vec: &mut [T]) {
-        vec.sort_by_cached_key(|x| format!("{:?}", x))
+        vec.sort_by_cached_key(|x| format!("{x:?}"))
     }
 
     fn is_fn_trait(&self, path: &Path) -> bool {
diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs
index 9d744237b57..dad2aa4061d 100644
--- a/src/librustdoc/clean/blanket_impl.rs
+++ b/src/librustdoc/clean/blanket_impl.rs
@@ -17,7 +17,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
         let param_env = cx.tcx.param_env(item_def_id);
         let ty = cx.tcx.type_of(item_def_id);
 
-        trace!("get_blanket_impls({:?})", ty);
+        trace!("get_blanket_impls({ty:?})");
         let mut impls = Vec::new();
         for trait_def_id in cx.tcx.all_traits() {
             if !cx.cache.effective_visibilities.is_reachable(cx.tcx, trait_def_id)
@@ -72,7 +72,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
                     .into_iter()
                     .chain(Some(ty::Binder::dummy(impl_trait_ref).to_predicate(infcx.tcx)));
                 for predicate in predicates {
-                    debug!("testing predicate {:?}", predicate);
+                    debug!("testing predicate {predicate:?}");
                     let obligation = traits::Obligation::new(
                         infcx.tcx,
                         traits::ObligationCause::dummy(),
diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs
index 7652f27e51c..ab5aec12fe7 100644
--- a/src/librustdoc/clean/cfg.rs
+++ b/src/librustdoc/clean/cfg.rs
@@ -434,9 +434,9 @@ impl<'a> fmt::Display for Display<'a> {
                     }
                     if let (true, Cfg::Cfg(_, Some(feat))) = (short_longhand, sub_cfg) {
                         if self.1.is_html() {
-                            write!(fmt, "<code>{}</code>", feat)?;
+                            write!(fmt, "<code>{feat}</code>")?;
                         } else {
-                            write!(fmt, "`{}`", feat)?;
+                            write!(fmt, "`{feat}`")?;
                         }
                     } else {
                         write_with_opt_paren(fmt, !sub_cfg.is_all(), Display(sub_cfg, self.1))?;
@@ -471,9 +471,9 @@ impl<'a> fmt::Display for Display<'a> {
                     }
                     if let (true, Cfg::Cfg(_, Some(feat))) = (short_longhand, sub_cfg) {
                         if self.1.is_html() {
-                            write!(fmt, "<code>{}</code>", feat)?;
+                            write!(fmt, "<code>{feat}</code>")?;
                         } else {
-                            write!(fmt, "`{}`", feat)?;
+                            write!(fmt, "`{feat}`")?;
                         }
                     } else {
                         write_with_opt_paren(fmt, !sub_cfg.is_simple(), Display(sub_cfg, self.1))?;
@@ -552,21 +552,21 @@ impl<'a> fmt::Display for Display<'a> {
                         "sgx" => "SGX",
                         _ => "",
                     },
-                    (sym::target_endian, Some(endian)) => return write!(fmt, "{}-endian", endian),
-                    (sym::target_pointer_width, Some(bits)) => return write!(fmt, "{}-bit", bits),
+                    (sym::target_endian, Some(endian)) => return write!(fmt, "{endian}-endian"),
+                    (sym::target_pointer_width, Some(bits)) => return write!(fmt, "{bits}-bit"),
                     (sym::target_feature, Some(feat)) => match self.1 {
                         Format::LongHtml => {
-                            return write!(fmt, "target feature <code>{}</code>", feat);
+                            return write!(fmt, "target feature <code>{feat}</code>");
                         }
-                        Format::LongPlain => return write!(fmt, "target feature `{}`", feat),
-                        Format::ShortHtml => return write!(fmt, "<code>{}</code>", feat),
+                        Format::LongPlain => return write!(fmt, "target feature `{feat}`"),
+                        Format::ShortHtml => return write!(fmt, "<code>{feat}</code>"),
                     },
                     (sym::feature, Some(feat)) => match self.1 {
                         Format::LongHtml => {
-                            return write!(fmt, "crate feature <code>{}</code>", feat);
+                            return write!(fmt, "crate feature <code>{feat}</code>");
                         }
-                        Format::LongPlain => return write!(fmt, "crate feature `{}`", feat),
-                        Format::ShortHtml => return write!(fmt, "<code>{}</code>", feat),
+                        Format::LongPlain => return write!(fmt, "crate feature `{feat}`"),
+                        Format::ShortHtml => return write!(fmt, "<code>{feat}</code>"),
                     },
                     _ => "",
                 };
@@ -581,12 +581,12 @@ impl<'a> fmt::Display for Display<'a> {
                             Escape(v.as_str())
                         )
                     } else {
-                        write!(fmt, r#"`{}="{}"`"#, name, v)
+                        write!(fmt, r#"`{name}="{v}"`"#)
                     }
                 } else if self.1.is_html() {
                     write!(fmt, "<code>{}</code>", Escape(name.as_str()))
                 } else {
-                    write!(fmt, "`{}`", name)
+                    write!(fmt, "`{name}`")
                 }
             }
         }
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 2456e8818eb..cac21130740 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -50,7 +50,7 @@ pub(crate) fn try_inline(
     }
     let mut ret = Vec::new();
 
-    debug!("attrs={:?}", attrs);
+    debug!("attrs={attrs:?}");
 
     let attrs_without_docs = attrs.map(|(attrs, def_id)| {
         (attrs.into_iter().filter(|a| a.doc_str().is_none()).cloned().collect::<Vec<_>>(), def_id)
@@ -529,7 +529,7 @@ pub(crate) fn build_impl(
     }
 
     let (merged_attrs, cfg) = merge_attrs(cx, load_attrs(cx, did), attrs);
-    trace!("merged_attrs={:?}", merged_attrs);
+    trace!("merged_attrs={merged_attrs:?}");
 
     trace!(
         "build_impl: impl {:?} for {:?}",
@@ -781,7 +781,7 @@ pub(crate) fn record_extern_trait(cx: &mut DocContext<'_>, did: DefId) {
         cx.active_extern_traits.insert(did);
     }
 
-    debug!("record_extern_trait: {:?}", did);
+    debug!("record_extern_trait: {did:?}");
     let trait_ = build_external_trait(cx, did);
 
     cx.external_traits.borrow_mut().insert(did, trait_);
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 624f1620f2c..ee1d0be27bf 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -215,7 +215,7 @@ pub(crate) fn clean_trait_ref_with_bindings<'tcx>(
 ) -> Path {
     let kind = cx.tcx.def_kind(trait_ref.def_id()).into();
     if !matches!(kind, ItemType::Trait | ItemType::TraitAlias) {
-        span_bug!(cx.tcx.def_span(trait_ref.def_id()), "`TraitRef` had unexpected kind {:?}", kind);
+        span_bug!(cx.tcx.def_span(trait_ref.def_id()), "`TraitRef` had unexpected kind {kind:?}");
     }
     inline::record_extern_fqn(cx, trait_ref.def_id(), kind);
     let path =
@@ -304,7 +304,7 @@ pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option<Life
         | ty::ReError(_)
         | ty::RePlaceholder(..)
         | ty::ReErased => {
-            debug!("cannot clean region {:?}", region);
+            debug!("cannot clean region {region:?}");
             None
         }
     }
@@ -1867,11 +1867,11 @@ fn normalize<'tcx>(
         .map(|resolved| infcx.resolve_vars_if_possible(resolved.value));
     match normalized {
         Ok(normalized_value) => {
-            debug!("normalized {:?} to {:?}", ty, normalized_value);
+            debug!("normalized {ty:?} to {normalized_value:?}");
             Some(normalized_value)
         }
         Err(err) => {
-            debug!("failed to normalize {:?}: {:?}", ty, err);
+            debug!("failed to normalize {ty:?}: {err:?}");
             None
         }
     }
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index cb089ddd09a..49bde1d3152 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -78,7 +78,7 @@ impl ItemId {
     #[track_caller]
     pub(crate) fn expect_def_id(self) -> DefId {
         self.as_def_id()
-            .unwrap_or_else(|| panic!("ItemId::expect_def_id: `{:?}` isn't a DefId", self))
+            .unwrap_or_else(|| panic!("ItemId::expect_def_id: `{self:?}` isn't a DefId"))
     }
 
     #[inline]
@@ -352,7 +352,7 @@ fn is_field_vis_inherited(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
     match tcx.def_kind(parent) {
         DefKind::Struct | DefKind::Union => false,
         DefKind::Variant => true,
-        parent_kind => panic!("unexpected parent kind: {:?}", parent_kind),
+        parent_kind => panic!("unexpected parent kind: {parent_kind:?}"),
     }
 }
 
@@ -436,7 +436,7 @@ impl Item {
         attrs: Box<Attributes>,
         cfg: Option<Arc<Cfg>>,
     ) -> Item {
-        trace!("name={:?}, def_id={:?} cfg={:?}", name, def_id, cfg);
+        trace!("name={name:?}, def_id={def_id:?} cfg={cfg:?}");
 
         Item {
             item_id: def_id.into(),
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 3c79ce57782..80a7a33d2bd 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -218,7 +218,7 @@ pub(crate) fn build_deref_target_impls(
 
 pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
     use rustc_hir::*;
-    debug!("trying to get a name from pattern: {:?}", p);
+    debug!("trying to get a name from pattern: {p:?}");
 
     Symbol::intern(&match p.kind {
         PatKind::Wild | PatKind::Struct(..) => return kw::Underscore,
@@ -461,7 +461,7 @@ pub(crate) fn print_const_expr(tcx: TyCtxt<'_>, body: hir::BodyId) -> String {
 
 /// Given a type Path, resolve it to a Type using the TyCtxt
 pub(crate) fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type {
-    debug!("resolve_type({:?})", path);
+    debug!("resolve_type({path:?})");
 
     match path.res {
         Res::PrimTy(p) => Primitive(PrimitiveType::from(p)),
@@ -500,7 +500,7 @@ pub(crate) fn get_auto_trait_and_blanket_impls(
 /// [`href()`]: crate::html::format::href
 pub(crate) fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId {
     use DefKind::*;
-    debug!("register_res({:?})", res);
+    debug!("register_res({res:?})");
 
     let (kind, did) = match res {
         Res::Def(
@@ -523,7 +523,7 @@ pub(crate) fn register_res(cx: &mut DocContext<'_>, res: Res) -> DefId {
             did,
         ) => (kind.into(), did),
 
-        _ => panic!("register_res: unexpected {:?}", res),
+        _ => panic!("register_res: unexpected {res:?}"),
     };
     if did.is_local() {
         return did;
@@ -601,8 +601,12 @@ pub(super) fn render_macro_arms<'a>(
 ) -> String {
     let mut out = String::new();
     for matcher in matchers {
-        writeln!(out, "    {} => {{ ... }}{}", render_macro_matcher(tcx, matcher), arm_delim)
-            .unwrap();
+        writeln!(
+            out,
+            "    {matcher} => {{ ... }}{arm_delim}",
+            matcher = render_macro_matcher(tcx, matcher),
+        )
+        .unwrap();
     }
     out
 }
@@ -618,21 +622,21 @@ pub(super) fn display_macro_source(
     let matchers = def.body.tokens.chunks(4).map(|arm| &arm[0]);
 
     if def.macro_rules {
-        format!("macro_rules! {} {{\n{}}}", name, render_macro_arms(cx.tcx, matchers, ";"))
+        format!("macro_rules! {name} {{\n{arms}}}", arms = render_macro_arms(cx.tcx, matchers, ";"))
     } else {
         if matchers.len() <= 1 {
             format!(
-                "{}macro {}{} {{\n    ...\n}}",
-                visibility_to_src_with_space(Some(vis), cx.tcx, def_id),
-                name,
-                matchers.map(|matcher| render_macro_matcher(cx.tcx, matcher)).collect::<String>(),
+                "{vis}macro {name}{matchers} {{\n    ...\n}}",
+                vis = visibility_to_src_with_space(Some(vis), cx.tcx, def_id),
+                matchers = matchers
+                    .map(|matcher| render_macro_matcher(cx.tcx, matcher))
+                    .collect::<String>(),
             )
         } else {
             format!(
-                "{}macro {} {{\n{}}}",
-                visibility_to_src_with_space(Some(vis), cx.tcx, def_id),
-                name,
-                render_macro_arms(cx.tcx, matchers, ","),
+                "{vis}macro {name} {{\n{arms}}}",
+                vis = visibility_to_src_with_space(Some(vis), cx.tcx, def_id),
+                arms = render_macro_arms(cx.tcx, matchers, ","),
             )
         }
     }
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index 217f1a6ee6b..81fb13f4166 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -50,7 +50,7 @@ impl TryFrom<&str> for OutputFormat {
         match value {
             "json" => Ok(OutputFormat::Json),
             "html" => Ok(OutputFormat::Html),
-            _ => Err(format!("unknown output format `{}`", value)),
+            _ => Err(format!("unknown output format `{value}`")),
         }
     }
 }
@@ -383,7 +383,7 @@ impl Options {
                 match kind.parse() {
                     Ok(kind) => emit.push(kind),
                     Err(()) => {
-                        diag.err(format!("unrecognized emission type: {}", kind));
+                        diag.err(format!("unrecognized emission type: {kind}"));
                         return Err(1);
                     }
                 }
@@ -415,7 +415,7 @@ impl Options {
 
             println!("rustdoc: [check-theme] Starting tests! (Ignoring all other arguments)");
             for theme_file in to_check.iter() {
-                print!(" - Checking \"{}\"...", theme_file);
+                print!(" - Checking \"{theme_file}\"...");
                 let (success, differences) = theme::test_theme_against(theme_file, &paths, &diag);
                 if !differences.is_empty() || !success {
                     println!(" FAILED");
@@ -556,30 +556,28 @@ impl Options {
                 matches.opt_strs("theme").iter().map(|s| (PathBuf::from(&s), s.to_owned()))
             {
                 if !theme_file.is_file() {
-                    diag.struct_err(format!("invalid argument: \"{}\"", theme_s))
+                    diag.struct_err(format!("invalid argument: \"{theme_s}\""))
                         .help("arguments to --theme must be files")
                         .emit();
                     return Err(1);
                 }
                 if theme_file.extension() != Some(OsStr::new("css")) {
-                    diag.struct_err(format!("invalid argument: \"{}\"", theme_s))
+                    diag.struct_err(format!("invalid argument: \"{theme_s}\""))
                         .help("arguments to --theme must have a .css extension")
                         .emit();
                     return Err(1);
                 }
                 let (success, ret) = theme::test_theme_against(&theme_file, &paths, &diag);
                 if !success {
-                    diag.struct_err(format!("error loading theme file: \"{}\"", theme_s)).emit();
+                    diag.struct_err(format!("error loading theme file: \"{theme_s}\"")).emit();
                     return Err(1);
                 } else if !ret.is_empty() {
                     diag.struct_warn(format!(
-                        "theme file \"{}\" is missing CSS rules from the default theme",
-                        theme_s
+                        "theme file \"{theme_s}\" is missing CSS rules from the default theme",
                     ))
                     .warn("the theme may appear incorrect when loaded")
                     .help(format!(
-                        "to see what rules are missing, call `rustdoc --check-theme \"{}\"`",
-                        theme_s
+                        "to see what rules are missing, call `rustdoc --check-theme \"{theme_s}\"`",
                     ))
                     .emit();
                 }
@@ -608,7 +606,7 @@ impl Options {
         match matches.opt_str("r").as_deref() {
             Some("rust") | None => {}
             Some(s) => {
-                diag.struct_err(format!("unknown input format: {}", s)).emit();
+                diag.struct_err(format!("unknown input format: {s}")).emit();
                 return Err(1);
             }
         }
@@ -628,7 +626,7 @@ impl Options {
         let crate_types = match parse_crate_types_from_list(matches.opt_strs("crate-type")) {
             Ok(types) => types,
             Err(e) => {
-                diag.struct_err(format!("unknown crate type: {}", e)).emit();
+                diag.struct_err(format!("unknown crate type: {e}")).emit();
                 return Err(1);
             }
         };
@@ -787,7 +785,7 @@ fn check_deprecated_options(matches: &getopts::Matches, diag: &rustc_errors::Han
 
     for &flag in deprecated_flags.iter() {
         if matches.opt_present(flag) {
-            diag.struct_warn(format!("the `{}` flag is deprecated", flag))
+            diag.struct_warn(format!("the `{flag}` flag is deprecated"))
                 .note(
                     "see issue #44136 <https://github.com/rust-lang/rust/issues/44136> \
                     for more information",
@@ -800,7 +798,7 @@ fn check_deprecated_options(matches: &getopts::Matches, diag: &rustc_errors::Han
 
     for &flag in removed_flags.iter() {
         if matches.opt_present(flag) {
-            let mut err = diag.struct_warn(format!("the `{}` flag no longer functions", flag));
+            let mut err = diag.struct_warn(format!("the `{flag}` flag no longer functions"));
             err.note(
                 "see issue #44136 <https://github.com/rust-lang/rust/issues/44136> \
                 for more information",
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index d7da8120996..4c8dab61f0c 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -283,7 +283,7 @@ pub(crate) fn create_config(
 
                 let hir = tcx.hir();
                 let body = hir.body(hir.body_owned_by(def_id));
-                debug!("visiting body for {:?}", def_id);
+                debug!("visiting body for {def_id:?}");
                 EmitIgnoredResolutionErrors::new(tcx).visit_body(body);
                 (rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id)
             };
@@ -377,7 +377,7 @@ pub(crate) fn run_global_ctxt(
 
     fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler, sp: Span) {
         let mut msg =
-            diag.struct_span_warn(sp, format!("the `#![doc({})]` attribute is deprecated", name));
+            diag.struct_span_warn(sp, format!("the `#![doc({name})]` attribute is deprecated"));
         msg.note(
             "see issue #44136 <https://github.com/rust-lang/rust/issues/44136> \
             for more information",
@@ -470,7 +470,7 @@ impl<'tcx> Visitor<'tcx> for EmitIgnoredResolutionErrors<'tcx> {
     }
 
     fn visit_path(&mut self, path: &Path<'tcx>, _id: HirId) {
-        debug!("visiting path {:?}", path);
+        debug!("visiting path {path:?}");
         if path.res == Res::Err {
             // We have less context here than in rustc_resolve,
             // so we can only emit the name and span.
@@ -487,8 +487,7 @@ impl<'tcx> Visitor<'tcx> for EmitIgnoredResolutionErrors<'tcx> {
                 self.tcx.sess,
                 path.span,
                 E0433,
-                "failed to resolve: {}",
-                label
+                "failed to resolve: {label}",
             );
             err.span_label(path.span, label);
             err.note("this error was originally ignored because you are running `rustdoc`");
diff --git a/src/librustdoc/docfs.rs b/src/librustdoc/docfs.rs
index d58b8dc6ad4..82c1a503924 100644
--- a/src/librustdoc/docfs.rs
+++ b/src/librustdoc/docfs.rs
@@ -72,9 +72,9 @@ impl DocFS {
             let sender = self.errors.clone().expect("can't write after closing");
             self.pool.execute(move || {
                 fs::write(&path, contents).unwrap_or_else(|e| {
-                    sender.send(format!("\"{}\": {}", path.display(), e)).unwrap_or_else(|_| {
-                        panic!("failed to send error on \"{}\"", path.display())
-                    })
+                    sender.send(format!("\"{path}\": {e}", path = path.display())).unwrap_or_else(
+                        |_| panic!("failed to send error on \"{}\"", path.display()),
+                    )
                 });
             });
         } else {
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 3315ccad4d3..36d5adb6304 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -192,7 +192,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> {
                     // The allow lint level is not expected,
                     // as if allow is specified, no message
                     // is to be emitted.
-                    v => unreachable!("Invalid lint level '{}'", v),
+                    v => unreachable!("Invalid lint level '{v}'"),
                 })
                 .unwrap_or("warn")
                 .to_string();
@@ -404,7 +404,7 @@ fn run_test(
     compiler.stdin(Stdio::piped());
     compiler.stderr(Stdio::piped());
 
-    debug!("compiler invocation for doctest: {:?}", compiler);
+    debug!("compiler invocation for doctest: {compiler:?}");
 
     let mut child = compiler.spawn().expect("Failed to spawn rustc process");
     {
@@ -469,7 +469,9 @@ fn run_test(
     // Run the code!
     let mut cmd;
 
+    let output_file = make_maybe_absolute_path(output_file);
     if let Some(tool) = runtool {
+        let tool = make_maybe_absolute_path(tool.into());
         cmd = Command::new(tool);
         cmd.args(runtool_args);
         cmd.arg(output_file);
@@ -503,6 +505,20 @@ fn run_test(
     Ok(())
 }
 
+/// Converts a path intended to use as a command to absolute if it is
+/// relative, and not a single component.
+///
+/// This is needed to deal with relative paths interacting with
+/// `Command::current_dir` in a platform-specific way.
+fn make_maybe_absolute_path(path: PathBuf) -> PathBuf {
+    if path.components().count() == 1 {
+        // Look up process via PATH.
+        path
+    } else {
+        std::env::current_dir().map(|c| c.join(&path)).unwrap_or_else(|_| path)
+    }
+}
+
 /// Transforms a test into code that can be compiled into a Rust binary, and returns the number of
 /// lines before the test code begins as well as if the output stream supports colors or not.
 pub(crate) fn make_test(
@@ -933,7 +949,7 @@ impl Collector {
         if !item_path.is_empty() {
             item_path.push(' ');
         }
-        format!("{} - {}(line {})", filename.prefer_local(), item_path, line)
+        format!("{} - {item_path}(line {line})", filename.prefer_local())
     }
 
     pub(crate) fn set_position(&mut self, position: Span) {
@@ -1010,7 +1026,7 @@ impl Tester for Collector {
             path.push(&test_id);
 
             if let Err(err) = std::fs::create_dir_all(&path) {
-                eprintln!("Couldn't create directory for doctest executables: {}", err);
+                eprintln!("Couldn't create directory for doctest executables: {err}");
                 panic::resume_unwind(Box::new(()));
             }
 
@@ -1079,7 +1095,7 @@ impl Tester for Collector {
                             eprint!("Test executable succeeded, but it's marked `should_panic`.");
                         }
                         TestFailure::MissingErrorCodes(codes) => {
-                            eprint!("Some expected error codes were not found: {:?}", codes);
+                            eprint!("Some expected error codes were not found: {codes:?}");
                         }
                         TestFailure::ExecutionError(err) => {
                             eprint!("Couldn't run the test: {err}");
diff --git a/src/librustdoc/externalfiles.rs b/src/librustdoc/externalfiles.rs
index 88049c4ca00..f0ebb8e5a39 100644
--- a/src/librustdoc/externalfiles.rs
+++ b/src/librustdoc/externalfiles.rs
@@ -37,8 +37,7 @@ impl ExternalHtml {
         let bc = load_external_files(before_content, diag)?;
         let m_bc = load_external_files(md_before_content, diag)?;
         let bc = format!(
-            "{}{}",
-            bc,
+            "{bc}{}",
             Markdown {
                 content: &m_bc,
                 links: &[],
@@ -53,8 +52,7 @@ impl ExternalHtml {
         let ac = load_external_files(after_content, diag)?;
         let m_ac = load_external_files(md_after_content, diag)?;
         let ac = format!(
-            "{}{}",
-            ac,
+            "{ac}{}",
             Markdown {
                 content: &m_ac,
                 links: &[],
@@ -83,7 +81,11 @@ pub(crate) fn load_string<P: AsRef<Path>>(
     let contents = match fs::read(file_path) {
         Ok(bytes) => bytes,
         Err(e) => {
-            diag.struct_err(format!("error reading `{}`: {}", file_path.display(), e)).emit();
+            diag.struct_err(format!(
+                "error reading `{file_path}`: {e}",
+                file_path = file_path.display()
+            ))
+            .emit();
             return Err(LoadStringError::ReadFail);
         }
     };
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 58022046294..2f611c31a07 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -109,6 +109,10 @@ impl Buffer {
         self.buffer
     }
 
+    pub(crate) fn push(&mut self, c: char) {
+        self.buffer.push(c);
+    }
+
     pub(crate) fn push_str(&mut self, s: &str) {
         self.buffer.push_str(s);
     }
@@ -228,9 +232,9 @@ impl clean::GenericParamDef {
 
                 if let Some(default) = default {
                     if f.alternate() {
-                        write!(f, " = {:#}", default)?;
+                        write!(f, " = {default:#}")?;
                     } else {
-                        write!(f, " = {}", default)?;
+                        write!(f, " = {default}")?;
                     }
                 }
 
@@ -451,9 +455,9 @@ impl clean::GenericBound {
                     hir::TraitBoundModifier::MaybeConst => "",
                 };
                 if f.alternate() {
-                    write!(f, "{}{:#}", modifier_str, ty.print(cx))
+                    write!(f, "{modifier_str}{ty:#}", ty = ty.print(cx))
                 } else {
-                    write!(f, "{}{}", modifier_str, ty.print(cx))
+                    write!(f, "{modifier_str}{ty}", ty = ty.print(cx))
                 }
             }
         })
@@ -599,7 +603,7 @@ fn generate_macro_def_id_path(
     let cstore = CStore::from_tcx(tcx);
     // We need this to prevent a `panic` when this function is used from intra doc links...
     if !cstore.has_crate_data(def_id.krate) {
-        debug!("No data for crate {}", crate_name);
+        debug!("No data for crate {crate_name}");
         return Err(HrefError::NotInExternalCache);
     }
     // Check to see if it is a macro 2.0 or built-in macro.
@@ -631,19 +635,18 @@ fn generate_macro_def_id_path(
     let url = match cache.extern_locations[&def_id.krate] {
         ExternalLocation::Remote(ref s) => {
             // `ExternalLocation::Remote` always end with a `/`.
-            format!("{}{}", s, path.iter().map(|p| p.as_str()).join("/"))
+            format!("{s}{path}", path = path.iter().map(|p| p.as_str()).join("/"))
         }
         ExternalLocation::Local => {
             // `root_path` always end with a `/`.
             format!(
-                "{}{}/{}",
-                root_path.unwrap_or(""),
-                crate_name,
-                path.iter().map(|p| p.as_str()).join("/")
+                "{root_path}{crate_name}/{path}",
+                root_path = root_path.unwrap_or(""),
+                path = path.iter().map(|p| p.as_str()).join("/")
             )
         }
         ExternalLocation::Unknown => {
-            debug!("crate {} not in cache when linkifying macros", crate_name);
+            debug!("crate {crate_name} not in cache when linkifying macros");
             return Err(HrefError::NotInExternalCache);
         }
     };
@@ -732,7 +735,7 @@ pub(crate) fn href_with_root_path(
         _ => {
             let prefix = shortty.as_str();
             let last = fqp.last().unwrap();
-            url_parts.push_fmt(format_args!("{}.{}.html", prefix, last));
+            url_parts.push_fmt(format_args!("{prefix}.{last}.html"));
         }
     }
     Ok((url_parts.finish(), shortty, fqp.to_vec()))
@@ -828,9 +831,9 @@ fn resolved_path<'cx>(
         let path = if use_absolute {
             if let Ok((_, _, fqp)) = href(did, cx) {
                 format!(
-                    "{}::{}",
-                    join_with_double_colon(&fqp[..fqp.len() - 1]),
-                    anchor(did, *fqp.last().unwrap(), cx)
+                    "{path}::{anchor}",
+                    path = join_with_double_colon(&fqp[..fqp.len() - 1]),
+                    anchor = anchor(did, *fqp.last().unwrap(), cx)
                 )
             } else {
                 last.name.to_string()
@@ -838,7 +841,7 @@ fn resolved_path<'cx>(
         } else {
             anchor(did, last.name, cx).to_string()
         };
-        write!(w, "{}{}", path, last.args.print(cx))?;
+        write!(w, "{path}{args}", args = last.args.print(cx))?;
     }
     Ok(())
 }
@@ -906,7 +909,7 @@ fn primitive_link_fragment(
             None => {}
         }
     }
-    write!(f, "{}", name)?;
+    f.write_str(name)?;
     if needs_termination {
         write!(f, "</a>")?;
     }
@@ -946,15 +949,11 @@ pub(crate) fn anchor<'a, 'cx: 'a>(
         if let Ok((url, short_ty, fqp)) = parts {
             write!(
                 f,
-                r#"<a class="{}" href="{}" title="{} {}">{}</a>"#,
-                short_ty,
-                url,
-                short_ty,
-                join_with_double_colon(&fqp),
-                text.as_str()
+                r#"<a class="{short_ty}" href="{url}" title="{short_ty} {path}">{text}</a>"#,
+                path = join_with_double_colon(&fqp),
             )
         } else {
-            write!(f, "{}", text)
+            f.write_str(text.as_str())
         }
     })
 }
@@ -965,10 +964,10 @@ fn fmt_type<'cx>(
     use_absolute: bool,
     cx: &'cx Context<'_>,
 ) -> fmt::Result {
-    trace!("fmt_type(t = {:?})", t);
+    trace!("fmt_type(t = {t:?})");
 
     match *t {
-        clean::Generic(name) => write!(f, "{}", name),
+        clean::Generic(name) => f.write_str(name.as_str()),
         clean::Type::Path { ref path } => {
             // Paths like `T::Output` and `Self::Output` should be rendered with all segments.
             let did = path.def_id();
@@ -1085,13 +1084,13 @@ fn fmt_type<'cx>(
 
             if matches!(**t, clean::Generic(_)) || t.is_assoc_ty() {
                 let text = if f.alternate() {
-                    format!("*{} {:#}", m, t.print(cx))
+                    format!("*{m} {ty:#}", ty = t.print(cx))
                 } else {
-                    format!("*{} {}", m, t.print(cx))
+                    format!("*{m} {ty}", ty = t.print(cx))
                 };
                 primitive_link(f, clean::PrimitiveType::RawPointer, &text, cx)
             } else {
-                primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{} ", m), cx)?;
+                primitive_link(f, clean::PrimitiveType::RawPointer, &format!("*{m} "), cx)?;
                 fmt::Display::fmt(&t.print(cx), f)
             }
         }
@@ -1445,11 +1444,20 @@ impl clean::FnDecl {
                     clean::SelfValue => {
                         write!(f, "self")?;
                     }
-                    clean::SelfBorrowed(Some(ref lt), mtbl) => {
-                        write!(f, "{}{} {}self", amp, lt.print(), mtbl.print_with_space())?;
+                    clean::SelfBorrowed(Some(ref lt), mutability) => {
+                        write!(
+                            f,
+                            "{amp}{lifetime} {mutability}self",
+                            lifetime = lt.print(),
+                            mutability = mutability.print_with_space(),
+                        )?;
                     }
-                    clean::SelfBorrowed(None, mtbl) => {
-                        write!(f, "{}{}self", amp, mtbl.print_with_space())?;
+                    clean::SelfBorrowed(None, mutability) => {
+                        write!(
+                            f,
+                            "{amp}{mutability}self",
+                            mutability = mutability.print_with_space(),
+                        )?;
                     }
                     clean::SelfExplicit(ref typ) => {
                         write!(f, "self: ")?;
@@ -1523,7 +1531,7 @@ pub(crate) fn visibility_print_with_space<'a, 'tcx: 'a>(
                 "pub(super) ".into()
             } else {
                 let path = cx.tcx().def_path(vis_did);
-                debug!("path={:?}", path);
+                debug!("path={path:?}");
                 // modified from `resolved_path()` to work with `DefPathData`
                 let last_name = path.data.last().unwrap().data.get_opt_name().unwrap();
                 let anchor = anchor(vis_did, last_name, cx);
@@ -1532,12 +1540,12 @@ pub(crate) fn visibility_print_with_space<'a, 'tcx: 'a>(
                 for seg in &path.data[..path.data.len() - 1] {
                     let _ = write!(s, "{}::", seg.data.get_opt_name().unwrap());
                 }
-                let _ = write!(s, "{}) ", anchor);
+                let _ = write!(s, "{anchor}) ");
                 s.into()
             }
         }
     };
-    display_fn(move |f| write!(f, "{}", to_print))
+    display_fn(move |f| f.write_str(&to_print))
 }
 
 /// This function is the same as print_with_space, except that it renders no links.
@@ -1632,7 +1640,7 @@ impl clean::Import {
                 if name == self.source.path.last() {
                     write!(f, "use {};", self.source.print(cx))
                 } else {
-                    write!(f, "use {} as {};", self.source.print(cx), name)
+                    write!(f, "use {source} as {name};", source = self.source.print(cx))
                 }
             }
             clean::ImportKind::Glob => {
@@ -1661,7 +1669,7 @@ impl clean::ImportSource {
                 if let hir::def::Res::PrimTy(p) = self.path.res {
                     primitive_link(f, PrimitiveType::from(p), name.as_str(), cx)?;
                 } else {
-                    write!(f, "{}", name)?;
+                    f.write_str(name.as_str())?;
                 }
                 Ok(())
             }
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index a99ac0f4e05..039e8cdb987 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -929,15 +929,15 @@ fn string_without_closing_tag<T: Display>(
     open_tag: bool,
 ) -> Option<&'static str> {
     let Some(klass) = klass else {
-        write!(out, "{}", text).unwrap();
+        write!(out, "{text}").unwrap();
         return None;
     };
     let Some(def_span) = klass.get_span() else {
         if !open_tag {
-            write!(out, "{}", text).unwrap();
+            write!(out, "{text}").unwrap();
             return None;
         }
-        write!(out, "<span class=\"{}\">{}", klass.as_html(), text).unwrap();
+        write!(out, "<span class=\"{klass}\">{text}", klass = klass.as_html()).unwrap();
         return Some("</span>");
     };
 
@@ -947,14 +947,17 @@ fn string_without_closing_tag<T: Display>(
             match t {
                 "self" | "Self" => write!(
                     &mut path,
-                    "<span class=\"{}\">{}</span>",
-                    Class::Self_(DUMMY_SP).as_html(),
-                    t
+                    "<span class=\"{klass}\">{t}</span>",
+                    klass = Class::Self_(DUMMY_SP).as_html(),
                 ),
                 "crate" | "super" => {
-                    write!(&mut path, "<span class=\"{}\">{}</span>", Class::KeyWord.as_html(), t)
+                    write!(
+                        &mut path,
+                        "<span class=\"{klass}\">{t}</span>",
+                        klass = Class::KeyWord.as_html(),
+                    )
                 }
-                t => write!(&mut path, "{}", t),
+                t => write!(&mut path, "{t}"),
             }
             .expect("Failed to build source HTML path");
             path
@@ -997,13 +1000,13 @@ fn string_without_closing_tag<T: Display>(
             if !open_tag {
                 // We're already inside an element which has the same klass, no need to give it
                 // again.
-                write!(out, "<a href=\"{}\">{}", href, text_s).unwrap();
+                write!(out, "<a href=\"{href}\">{text_s}").unwrap();
             } else {
                 let klass_s = klass.as_html();
                 if klass_s.is_empty() {
-                    write!(out, "<a href=\"{}\">{}", href, text_s).unwrap();
+                    write!(out, "<a href=\"{href}\">{text_s}").unwrap();
                 } else {
-                    write!(out, "<a class=\"{}\" href=\"{}\">{}", klass_s, href, text_s).unwrap();
+                    write!(out, "<a class=\"{klass_s}\" href=\"{href}\">{text_s}").unwrap();
                 }
             }
             return Some("</a>");
@@ -1018,7 +1021,7 @@ fn string_without_closing_tag<T: Display>(
         out.write_str(&text_s).unwrap();
         Some("")
     } else {
-        write!(out, "<span class=\"{}\">{}", klass_s, text_s).unwrap();
+        write!(out, "<span class=\"{klass_s}\">{text_s}").unwrap();
         Some("</span>")
     }
 }
diff --git a/src/librustdoc/html/highlight/tests.rs b/src/librustdoc/html/highlight/tests.rs
index 2c93b9a097f..4c0874a686f 100644
--- a/src/librustdoc/html/highlight/tests.rs
+++ b/src/librustdoc/html/highlight/tests.rs
@@ -23,7 +23,7 @@ fn test_html_highlighting() {
         let html = {
             let mut out = Buffer::new();
             write_code(&mut out, src, None, None);
-            format!("{}<pre><code>{}</code></pre>\n", STYLE, out.into_inner())
+            format!("{STYLE}<pre><code>{}</code></pre>\n", out.into_inner())
         };
         expect_file!["fixtures/sample.html"].assert_eq(&html);
     });
diff --git a/src/librustdoc/html/length_limit.rs b/src/librustdoc/html/length_limit.rs
index 4c8db2c6784..8562e103dc1 100644
--- a/src/librustdoc/html/length_limit.rs
+++ b/src/librustdoc/html/length_limit.rs
@@ -78,8 +78,7 @@ impl HtmlWithLimit {
     pub(super) fn open_tag(&mut self, tag_name: &'static str) {
         assert!(
             tag_name.chars().all(|c| ('a'..='z').contains(&c)),
-            "tag_name contained non-alphabetic chars: {:?}",
-            tag_name
+            "tag_name contained non-alphabetic chars: {tag_name:?}",
         );
         self.queued_tags.push(tag_name);
     }
@@ -88,7 +87,7 @@ impl HtmlWithLimit {
     pub(super) fn close_tag(&mut self) {
         match self.unclosed_tags.pop() {
             // Close the most recently opened tag.
-            Some(tag_name) => write!(self.buf, "</{}>", tag_name).unwrap(),
+            Some(tag_name) => write!(self.buf, "</{tag_name}>").unwrap(),
             // There are valid cases where `close_tag()` is called without
             // there being any tags to close. For example, this occurs when
             // a tag is opened after the length limit is exceeded;
@@ -101,7 +100,7 @@ impl HtmlWithLimit {
     /// Write all queued tags and add them to the `unclosed_tags` list.
     fn flush_queue(&mut self) {
         for tag_name in self.queued_tags.drain(..) {
-            write!(self.buf, "<{}>", tag_name).unwrap();
+            write!(self.buf, "<{tag_name}>").unwrap();
 
             self.unclosed_tags.push(tag_name);
         }
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 3fb7122fad3..98cc38a10d4 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -50,7 +50,7 @@ use crate::html::render::small_url_encode;
 use crate::html::toc::TocBuilder;
 
 use pulldown_cmark::{
-    html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag,
+    html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, OffsetIter, Options, Parser, Tag,
 };
 
 #[cfg(test)]
@@ -246,10 +246,9 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
                     return Some(Event::Html(
                         format!(
                             "<div class=\"example-wrap\">\
-                                 <pre class=\"language-{}\"><code>{}</code></pre>\
+                                 <pre class=\"language-{lang}\"><code>{text}</code></pre>\
                              </div>",
-                            lang,
-                            Escape(&original_text),
+                            text = Escape(&original_text),
                         )
                         .into(),
                     ));
@@ -288,8 +287,9 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
 
             let test_escaped = small_url_encode(test);
             Some(format!(
-                r#"<a class="test-arrow" target="_blank" href="{}?code={}{}&amp;edition={}">Run</a>"#,
-                url, test_escaped, channel, edition,
+                "<a class=\"test-arrow\" \
+                    target=\"_blank\" \
+                    href=\"{url}?code={test_escaped}{channel}&amp;edition={edition}\">Run</a>",
             ))
         });
 
@@ -308,7 +308,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
         // insert newline to clearly separate it from the
         // previous block so we can shorten the html output
         let mut s = Buffer::new();
-        s.push_str("\n");
+        s.push('\n');
 
         highlight::render_example_with_highlighting(
             &text,
@@ -349,7 +349,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
                 dest,
                 title,
             ))) => {
-                debug!("saw start of shortcut link to {} with title {}", dest, title);
+                debug!("saw start of shortcut link to {dest} with title {title}");
                 // If this is a shortcut link, it was resolved by the broken_link_callback.
                 // So the URL will already be updated properly.
                 let link = self.links.iter().find(|&link| *link.href == **dest);
@@ -370,7 +370,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
                 dest,
                 _,
             ))) => {
-                debug!("saw end of shortcut link to {}", dest);
+                debug!("saw end of shortcut link to {dest}");
                 if self.links.iter().any(|link| *link.href == **dest) {
                     assert!(self.shortcut_link.is_some(), "saw closing link without opening tag");
                     self.shortcut_link = None;
@@ -379,7 +379,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
             // Handle backticks in inline code blocks, but only if we're in the middle of a shortcut link.
             // [`fn@f`]
             Some(Event::Code(text)) => {
-                trace!("saw code {}", text);
+                trace!("saw code {text}");
                 if let Some(link) = self.shortcut_link {
                     // NOTE: this only replaces if the code block is the *entire* text.
                     // If only part of the link has code highlighting, the disambiguator will not be removed.
@@ -394,7 +394,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
                         l.href == link.href
                             && Some(&**text) == l.original_text.get(1..l.original_text.len() - 1)
                     }) {
-                        debug!("replacing {} with {}", text, link.new_text);
+                        debug!("replacing {text} with {new_text}", new_text = link.new_text);
                         *text = CowStr::Borrowed(&link.new_text);
                     }
                 }
@@ -402,7 +402,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
             // Replace plain text in links, but only in the middle of a shortcut link.
             // [fn@f]
             Some(Event::Text(text)) => {
-                trace!("saw text {}", text);
+                trace!("saw text {text}");
                 if let Some(link) = self.shortcut_link {
                     // NOTE: same limitations as `Event::Code`
                     if let Some(link) = self
@@ -410,7 +410,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for LinkReplacer<'a, I> {
                         .iter()
                         .find(|l| l.href == link.href && **text == *l.original_text)
                     {
-                        debug!("replacing {} with {}", text, link.new_text);
+                        debug!("replacing {text} with {new_text}", new_text = link.new_text);
                         *text = CowStr::Borrowed(&link.new_text);
                     }
                 }
@@ -522,12 +522,12 @@ impl<'a, 'b, 'ids, I: Iterator<Item = SpannedEvent<'a>>> Iterator
                 let mut html_header = String::new();
                 html::push_html(&mut html_header, self.buf.iter().map(|(ev, _)| ev.clone()));
                 let sec = builder.push(level as u32, html_header, id.clone());
-                self.buf.push_front((Event::Html(format!("{} ", sec).into()), 0..0));
+                self.buf.push_front((Event::Html(format!("{sec} ").into()), 0..0));
             }
 
             let level =
                 std::cmp::min(level as u32 + (self.heading_offset as u32), MAX_HEADER_LEVEL);
-            self.buf.push_back((Event::Html(format!("</a></h{}>", level).into()), 0..0));
+            self.buf.push_back((Event::Html(format!("</a></h{level}>").into()), 0..0));
 
             let start_tags = format!(
                 "<h{level} id=\"{id}\">\
@@ -681,14 +681,14 @@ impl<'a, I: Iterator<Item = SpannedEvent<'a>>> Iterator for Footnotes<'a, I> {
                         v.sort_by(|a, b| a.1.cmp(&b.1));
                         let mut ret = String::from("<div class=\"footnotes\"><hr><ol>");
                         for (mut content, id) in v {
-                            write!(ret, "<li id=\"fn{}\">", id).unwrap();
+                            write!(ret, "<li id=\"fn{id}\">").unwrap();
                             let mut is_paragraph = false;
                             if let Some(&Event::End(Tag::Paragraph)) = content.last() {
                                 content.pop();
                                 is_paragraph = true;
                             }
                             html::push_html(&mut ret, content.into_iter());
-                            write!(ret, "&nbsp;<a href=\"#fnref{}\">↩</a>", id).unwrap();
+                            write!(ret, "&nbsp;<a href=\"#fnref{id}\">↩</a>").unwrap();
                             if is_paragraph {
                                 ret.push_str("</p>");
                             }
@@ -959,7 +959,7 @@ impl LangString {
                     } {
                         if let Some(extra) = extra {
                             extra.error_invalid_codeblock_attr(
-                                format!("unknown attribute `{}`. Did you mean `{}`?", x, flag),
+                                format!("unknown attribute `{x}`. Did you mean `{flag}`?"),
                                 help,
                             );
                         }
@@ -1038,7 +1038,7 @@ impl MarkdownWithToc<'_> {
             html::push_html(&mut s, p);
         }
 
-        format!("<nav id=\"TOC\">{}</nav>{}", toc.into_toc().print(), s)
+        format!("<nav id=\"TOC\">{toc}</nav>{s}", toc = toc.into_toc().print())
     }
 }
 
@@ -1240,6 +1240,7 @@ pub(crate) fn plain_text_summary(md: &str, link_names: &[RenderedLink]) -> Strin
 pub(crate) struct MarkdownLink {
     pub kind: LinkType,
     pub link: String,
+    pub display_text: Option<String>,
     pub range: MarkdownLinkRange,
 }
 
@@ -1263,8 +1264,8 @@ impl MarkdownLinkRange {
     }
 }
 
-pub(crate) fn markdown_links<R>(
-    md: &str,
+pub(crate) fn markdown_links<'md, R>(
+    md: &'md str,
     preprocess_link: impl Fn(MarkdownLink) -> Option<R>,
 ) -> Vec<R> {
     if md.is_empty() {
@@ -1375,32 +1376,90 @@ pub(crate) fn markdown_links<R>(
         MarkdownLinkRange::Destination(range.clone())
     };
 
-    Parser::new_with_broken_link_callback(
+    let mut broken_link_callback = |link: BrokenLink<'md>| Some((link.reference, "".into()));
+    let mut event_iter = Parser::new_with_broken_link_callback(
         md,
         main_body_opts(),
-        Some(&mut |link: BrokenLink<'_>| Some((link.reference, "".into()))),
+        Some(&mut broken_link_callback),
     )
-    .into_offset_iter()
-    .filter_map(|(event, span)| match event {
-        Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
-            let range = match link_type {
-                // Link is pulled from the link itself.
-                LinkType::ReferenceUnknown | LinkType::ShortcutUnknown => {
-                    span_for_offset_backward(span, b'[', b']')
-                }
-                LinkType::CollapsedUnknown => span_for_offset_forward(span, b'[', b']'),
-                LinkType::Inline => span_for_offset_backward(span, b'(', b')'),
-                // Link is pulled from elsewhere in the document.
-                LinkType::Reference | LinkType::Collapsed | LinkType::Shortcut => {
-                    span_for_link(&dest, span)
+    .into_offset_iter();
+    let mut links = Vec::new();
+
+    while let Some((event, span)) = event_iter.next() {
+        match event {
+            Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
+                let range = match link_type {
+                    // Link is pulled from the link itself.
+                    LinkType::ReferenceUnknown | LinkType::ShortcutUnknown => {
+                        span_for_offset_backward(span, b'[', b']')
+                    }
+                    LinkType::CollapsedUnknown => span_for_offset_forward(span, b'[', b']'),
+                    LinkType::Inline => span_for_offset_backward(span, b'(', b')'),
+                    // Link is pulled from elsewhere in the document.
+                    LinkType::Reference | LinkType::Collapsed | LinkType::Shortcut => {
+                        span_for_link(&dest, span)
+                    }
+                    LinkType::Autolink | LinkType::Email => unreachable!(),
+                };
+
+                let display_text = if matches!(
+                    link_type,
+                    LinkType::Inline
+                        | LinkType::ReferenceUnknown
+                        | LinkType::Reference
+                        | LinkType::Shortcut
+                        | LinkType::ShortcutUnknown
+                ) {
+                    collect_link_data(&mut event_iter)
+                } else {
+                    None
+                };
+
+                if let Some(link) = preprocess_link(MarkdownLink {
+                    kind: link_type,
+                    link: dest.into_string(),
+                    display_text,
+                    range,
+                }) {
+                    links.push(link);
                 }
-                LinkType::Autolink | LinkType::Email => unreachable!(),
-            };
-            preprocess_link(MarkdownLink { kind: link_type, range, link: dest.into_string() })
+            }
+            _ => {}
         }
-        _ => None,
-    })
-    .collect()
+    }
+
+    links
+}
+
+/// Collects additional data of link.
+fn collect_link_data<'input, 'callback>(
+    event_iter: &mut OffsetIter<'input, 'callback>,
+) -> Option<String> {
+    let mut display_text: Option<String> = None;
+    let mut append_text = |text: CowStr<'_>| {
+        if let Some(display_text) = &mut display_text {
+            display_text.push_str(&text);
+        } else {
+            display_text = Some(text.to_string());
+        }
+    };
+
+    while let Some((event, _span)) = event_iter.next() {
+        match event {
+            Event::Text(text) => {
+                append_text(text);
+            }
+            Event::Code(code) => {
+                append_text(code);
+            }
+            Event::End(_) => {
+                break;
+            }
+            _ => {}
+        }
+    }
+
+    display_text
 }
 
 #[derive(Debug)]
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 991edbddc6f..d7ff248a9bf 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -206,15 +206,14 @@ impl<'tcx> Context<'tcx> {
             format!("API documentation for the Rust `{}` crate.", self.shared.layout.krate)
         } else {
             format!(
-                "API documentation for the Rust `{}` {} in crate `{}`.",
-                it.name.as_ref().unwrap(),
-                tyname,
-                self.shared.layout.krate
+                "API documentation for the Rust `{name}` {tyname} in crate `{krate}`.",
+                name = it.name.as_ref().unwrap(),
+                krate = self.shared.layout.krate,
             )
         };
         let name;
         let tyname_s = if it.is_crate() {
-            name = format!("{} crate", tyname);
+            name = format!("{tyname} crate");
             name.as_str()
         } else {
             tyname.as_str()
@@ -264,7 +263,12 @@ impl<'tcx> Context<'tcx> {
                             current_path.push_str(&item_path(ty, names.last().unwrap().as_str()));
                             redirections.borrow_mut().insert(current_path, path);
                         }
-                        None => return layout::redirect(&format!("{}{}", self.root_path(), path)),
+                        None => {
+                            return layout::redirect(&format!(
+                                "{root}{path}",
+                                root = self.root_path()
+                            ));
+                        }
                     }
                 }
             }
@@ -382,11 +386,7 @@ impl<'tcx> Context<'tcx> {
             let hiline = span.hi(self.sess()).line;
             format!(
                 "#{}",
-                if loline == hiline {
-                    loline.to_string()
-                } else {
-                    format!("{}-{}", loline, hiline)
-                }
+                if loline == hiline { loline.to_string() } else { format!("{loline}-{hiline}") }
             )
         } else {
             "".to_string()
@@ -855,12 +855,12 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             // If the item is a macro, redirect from the old macro URL (with !)
             // to the new one (without).
             if item_type == ItemType::Macro {
-                let redir_name = format!("{}.{}!.html", item_type, name);
+                let redir_name = format!("{item_type}.{name}!.html");
                 if let Some(ref redirections) = self.shared.redirections {
                     let crate_name = &self.shared.layout.krate;
                     redirections.borrow_mut().insert(
-                        format!("{}/{}", crate_name, redir_name),
-                        format!("{}/{}", crate_name, file_name),
+                        format!("{crate_name}/{redir_name}"),
+                        format!("{crate_name}/{file_name}"),
                     );
                 } else {
                     let v = layout::redirect(file_name);
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 8a6e0b1ed51..ac9c180a6a8 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -85,7 +85,7 @@ use crate::DOC_RUST_LANG_ORG_CHANNEL;
 
 pub(crate) fn ensure_trailing_slash(v: &str) -> impl fmt::Display + '_ {
     crate::html::format::display_fn(move |f| {
-        if !v.ends_with('/') && !v.is_empty() { write!(f, "{}/", v) } else { f.write_str(v) }
+        if !v.ends_with('/') && !v.is_empty() { write!(f, "{v}/") } else { f.write_str(v) }
     })
 }
 
@@ -416,7 +416,7 @@ fn document<'a, 'cx: 'a>(
     heading_offset: HeadingOffset,
 ) -> impl fmt::Display + 'a + Captures<'cx> {
     if let Some(ref name) = item.name {
-        info!("Documenting {}", name);
+        info!("Documenting {name}");
     }
 
     display_fn(move |f| {
@@ -513,7 +513,7 @@ fn document_full_inner<'a, 'cx: 'a>(
 ) -> impl fmt::Display + 'a + Captures<'cx> {
     display_fn(move |f| {
         if let Some(s) = item.opt_doc_value() {
-            debug!("Doc block: =====\n{}\n=====", s);
+            debug!("Doc block: =====\n{s}\n=====");
             if is_collapsible {
                 write!(
                     f,
@@ -565,12 +565,10 @@ fn portability(item: &clean::Item, parent: Option<&clean::Item>) -> Option<Strin
     };
 
     debug!(
-        "Portability {:?} {:?} (parent: {:?}) - {:?} = {:?}",
-        item.name,
-        item.cfg,
-        parent,
-        parent.and_then(|p| p.cfg.as_ref()),
-        cfg
+        "Portability {name:?} {item_cfg:?} (parent: {parent:?}) - {parent_cfg:?} = {cfg:?}",
+        name = item.name,
+        item_cfg = item.cfg,
+        parent_cfg = parent.and_then(|p| p.cfg.as_ref()),
     );
 
     Some(cfg?.render_long_html())
@@ -1041,7 +1039,7 @@ fn render_attributes_in_pre<'a, 'b: 'a>(
 ) -> impl fmt::Display + Captures<'a> + Captures<'b> {
     crate::html::format::display_fn(move |f| {
         for a in it.attributes(tcx, false) {
-            writeln!(f, "{}{}", prefix, a)?;
+            writeln!(f, "{prefix}{a}")?;
         }
         Ok(())
     })
@@ -1245,7 +1243,10 @@ fn render_deref_methods(
             _ => None,
         })
         .expect("Expected associated type binding");
-    debug!("Render deref methods for {:#?}, target {:#?}", impl_.inner_impl().for_, target);
+    debug!(
+        "Render deref methods for {for_:#?}, target {target:#?}",
+        for_ = impl_.inner_impl().for_
+    );
     let what =
         AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut };
     if let Some(did) = target.def_id(cache) {
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index cfced799f1e..6cab3498622 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -310,9 +310,8 @@ fn toggle_open(mut w: impl fmt::Write, text: impl fmt::Display) {
         w,
         "<details class=\"toggle type-contents-toggle\">\
             <summary class=\"hideme\">\
-                <span>Show {}</span>\
+                <span>Show {text}</span>\
             </summary>",
-        text
     )
     .unwrap();
 }
@@ -412,7 +411,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
         )
     });
 
-    debug!("{:?}", indices);
+    debug!("{indices:?}");
     let mut last_section = None;
 
     for &idx in &indices {
@@ -431,8 +430,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
                 w,
                 "<h2 id=\"{id}\" class=\"small-section-header\">\
                     <a href=\"#{id}\">{name}</a>\
-                 </h2>{}",
-                ITEM_TABLE_OPEN,
+                 </h2>{ITEM_TABLE_OPEN}",
                 id = cx.derive_id(my_section.id()),
                 name = my_section.name(),
             );
@@ -485,7 +483,7 @@ fn item_module(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Item, items:
                 w.write_str(ITEM_TABLE_ROW_OPEN);
                 let id = match import.kind {
                     clean::ImportKind::Simple(s) => {
-                        format!(" id=\"{}\"", cx.derive_id(format!("reexport.{}", s)))
+                        format!(" id=\"{}\"", cx.derive_id(format!("reexport.{s}")))
                     }
                     clean::ImportKind::Glob => String::new(),
                 };
@@ -583,10 +581,8 @@ fn extra_info_tags<'a, 'tcx: 'a>(
             display_fn(move |f| {
                 write!(
                     f,
-                    r#"<span class="stab {}" title="{}">{}</span>"#,
-                    class,
-                    Escape(title),
-                    contents
+                    r#"<span class="stab {class}" title="{title}">{contents}</span>"#,
+                    title = Escape(title),
                 )
             })
         }
@@ -614,7 +610,12 @@ fn extra_info_tags<'a, 'tcx: 'a>(
             (cfg, _) => cfg.as_deref().cloned(),
         };
 
-        debug!("Portability name={:?} {:?} - {:?} = {:?}", item.name, item.cfg, parent.cfg, cfg);
+        debug!(
+            "Portability name={name:?} {cfg:?} - {parent_cfg:?} = {cfg:?}",
+            name = item.name,
+            cfg = item.cfg,
+            parent_cfg = parent.cfg
+        );
         if let Some(ref cfg) = cfg {
             write!(
                 f,
@@ -689,14 +690,13 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
     wrap_item(w, |mut w| {
         write!(
             w,
-            "{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,
+            "{attrs}{vis}{unsafety}{is_auto}trait {name}{generics}{bounds}",
             attrs = render_attributes_in_pre(it, "", tcx),
+            vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
+            unsafety = t.unsafety(tcx).print_with_space(),
+            is_auto = if t.is_auto(tcx) { "auto " } else { "" },
+            name = it.name.unwrap(),
+            generics = t.generics.print(cx),
         );
 
         if !t.generics.where_predicates.is_empty() {
@@ -742,11 +742,10 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
                 toggle_open(
                     &mut w,
                     format_args!(
-                        "{} associated constant{} and {} method{}",
-                        count_consts,
-                        pluralize(count_consts),
-                        count_methods,
-                        pluralize(count_methods),
+                        "{count_consts} associated constant{plural_const} and \
+                         {count_methods} method{plural_method}",
+                        plural_const = pluralize(count_consts),
+                        plural_method = pluralize(count_methods),
                     ),
                 );
             }
@@ -768,7 +767,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(&mut w, format_args!("{} methods", count_methods));
+                toggle_open(&mut w, format_args!("{count_methods} methods"));
             }
             if count_consts != 0 && count_methods != 0 {
                 w.write_str("\n");
@@ -837,9 +836,9 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
 
     fn trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &clean::Item, t: &clean::Item) {
         let name = m.name.unwrap();
-        info!("Documenting {} on {:?}", name, t.name);
+        info!("Documenting {name} on {ty_name:?}", ty_name = t.name);
         let item_type = m.type_();
-        let id = cx.derive_id(format!("{}.{}", item_type, name));
+        let id = cx.derive_id(format!("{item_type}.{name}"));
         let mut content = Buffer::empty_from(w);
         write!(&mut content, "{}", document(cx, m, Some(t), HeadingOffset::H5));
         let toggled = !content.is_empty();
@@ -847,7 +846,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean:
             let method_toggle_class = if item_type.is_method() { " method-toggle" } else { "" };
             write!(w, "<details class=\"toggle{method_toggle_class}\" open><summary>");
         }
-        write!(w, "<section id=\"{}\" class=\"method\">", id);
+        write!(w, "<section id=\"{id}\" class=\"method\">");
         render_rightside(w, cx, m, t, RenderMode::Normal);
         write!(w, "<h4 class=\"code-header\">");
         render_assoc_item(
@@ -1170,12 +1169,12 @@ fn item_trait_alias(
     wrap_item(w, |w| {
         write!(
             w,
-            "{attrs}trait {}{}{} = {};",
-            it.name.unwrap(),
-            t.generics.print(cx),
-            print_where_clause(&t.generics, cx, 0, Ending::Newline),
-            bounds(&t.bounds, true, cx),
+            "{attrs}trait {name}{generics}{where_b} = {bounds};",
             attrs = render_attributes_in_pre(it, "", cx.tcx()),
+            name = it.name.unwrap(),
+            generics = t.generics.print(cx),
+            where_b = print_where_clause(&t.generics, cx, 0, Ending::Newline),
+            bounds = bounds(&t.bounds, true, cx),
         )
         .unwrap();
     });
@@ -1198,12 +1197,12 @@ fn item_opaque_ty(
     wrap_item(w, |w| {
         write!(
             w,
-            "{attrs}type {}{}{where_clause} = impl {bounds};",
-            it.name.unwrap(),
-            t.generics.print(cx),
+            "{attrs}type {name}{generics}{where_clause} = impl {bounds};",
+            attrs = render_attributes_in_pre(it, "", cx.tcx()),
+            name = it.name.unwrap(),
+            generics = 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, "", cx.tcx()),
         )
         .unwrap();
     });
@@ -1223,13 +1222,13 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea
         wrap_item(w, |w| {
             write!(
                 w,
-                "{attrs}{}type {}{}{where_clause} = {type_};",
-                visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
-                it.name.unwrap(),
-                t.generics.print(cx),
+                "{attrs}{vis}type {name}{generics}{where_clause} = {type_};",
+                attrs = render_attributes_in_pre(it, "", cx.tcx()),
+                vis = visibility_print_with_space(it.visibility(cx.tcx()), it.item_id, cx),
+                name = it.name.unwrap(),
+                generics = 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, "", cx.tcx()),
             );
         });
     }
@@ -1354,7 +1353,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(&mut w, format_args!("{} variants", count_variants));
+                toggle_open(&mut w, format_args!("{count_variants} variants"));
             }
             for v in e.variants() {
                 w.write_str("    ");
@@ -1362,7 +1361,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean::
                 match *v.kind {
                     // FIXME(#101337): Show discriminant
                     clean::VariantItem(ref var) => match var.kind {
-                        clean::VariantKind::CLike => write!(w, "{}", name),
+                        clean::VariantKind::CLike => w.write_str(name.as_str()),
                         clean::VariantKind::Tuple(ref s) => {
                             write!(w, "{name}({})", print_tuple_struct_fields(cx, s),);
                         }
@@ -1418,7 +1417,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 {
-                write!(w, "({})", print_tuple_struct_fields(cx, s),);
+                write!(w, "({})", print_tuple_struct_fields(cx, s));
             }
             w.write_str("</h3></section>");
 
@@ -1617,7 +1616,7 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean
             for (index, (field, ty)) in fields.enumerate() {
                 let field_name =
                     field.name.map_or_else(|| index.to_string(), |sym| sym.as_str().to_string());
-                let id = cx.derive_id(format!("{}.{}", ItemType::StructField, field_name));
+                let id = cx.derive_id(format!("{typ}.{field_name}", typ = ItemType::StructField));
                 write!(
                     w,
                     "<span id=\"{id}\" class=\"{item_type} small-section-header\">\
@@ -1722,7 +1721,7 @@ pub(super) fn full_path(cx: &Context<'_>, item: &clean::Item) -> String {
 pub(super) fn item_path(ty: ItemType, name: &str) -> String {
     match ty {
         ItemType::Module => format!("{}index.html", ensure_trailing_slash(name)),
-        _ => format!("{}.{}.html", ty, name),
+        _ => format!("{ty}.{name}.html"),
     }
 }
 
@@ -1845,7 +1844,7 @@ fn render_union<'a, 'cx: 'a>(
             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));
+            toggle_open(&mut f, format_args!("{count_fields} fields"));
         }
 
         for field in fields {
@@ -1908,26 +1907,25 @@ fn render_struct(
             let has_visible_fields = count_fields > 0;
             let toggle = should_hide_fields(count_fields);
             if toggle {
-                toggle_open(&mut w, format_args!("{} fields", count_fields));
+                toggle_open(&mut w, format_args!("{count_fields} fields"));
             }
             for field in fields {
                 if let clean::StructFieldItem(ref ty) = *field.kind {
                     write!(
                         w,
-                        "\n{}    {}{}: {},",
-                        tab,
-                        visibility_print_with_space(field.visibility(tcx), field.item_id, cx),
-                        field.name.unwrap(),
-                        ty.print(cx),
+                        "\n{tab}    {vis}{name}: {ty},",
+                        vis = visibility_print_with_space(field.visibility(tcx), field.item_id, cx),
+                        name = field.name.unwrap(),
+                        ty = ty.print(cx),
                     );
                 }
             }
 
             if has_visible_fields {
                 if it.has_stripped_entries().unwrap() {
-                    write!(w, "\n{}    /* private fields */", tab);
+                    write!(w, "\n{tab}    /* private fields */");
                 }
-                write!(w, "\n{}", tab);
+                write!(w, "\n{tab}");
             } else if it.has_stripped_entries().unwrap() {
                 write!(w, " /* private fields */ ");
             }
diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs
index 455b4e9aefe..f3da610565c 100644
--- a/src/librustdoc/html/render/sidebar.rs
+++ b/src/librustdoc/html/render/sidebar.rs
@@ -330,7 +330,7 @@ fn sidebar_deref_methods<'a>(
 ) {
     let c = cx.cache();
 
-    debug!("found Deref: {:?}", impl_);
+    debug!("found Deref: {impl_:?}");
     if let Some((target, real_target)) =
         impl_.inner_impl().items.iter().find_map(|item| match *item.kind {
             clean::AssocTypeItem(box ref t, _) => Some(match *t {
@@ -340,7 +340,7 @@ fn sidebar_deref_methods<'a>(
             _ => None,
         })
     {
-        debug!("found target, real_target: {:?} {:?}", target, real_target);
+        debug!("found target, real_target: {target:?} {real_target:?}");
         if let Some(did) = target.def_id(c) &&
             let Some(type_did) = impl_.inner_impl().for_.def_id(c) &&
             // `impl Deref<Target = S> for S`
@@ -357,7 +357,7 @@ fn sidebar_deref_methods<'a>(
             })
             .and_then(|did| c.impls.get(&did));
         if let Some(impls) = inner_impl {
-            debug!("found inner_impl: {:?}", impls);
+            debug!("found inner_impl: {impls:?}");
             let mut ret = impls
                 .iter()
                 .filter(|i| i.inner_impl().trait_.is_none())
@@ -510,10 +510,10 @@ fn get_next_url(used_links: &mut FxHashSet<String>, url: String) -> String {
         return url;
     }
     let mut add = 1;
-    while !used_links.insert(format!("{}-{}", url, add)) {
+    while !used_links.insert(format!("{url}-{add}")) {
         add += 1;
     }
-    format!("{}-{}", url, add)
+    format!("{url}-{add}")
 }
 
 fn get_methods<'a>(
@@ -529,7 +529,7 @@ fn get_methods<'a>(
             Some(ref name) if !name.is_empty() && item.is_method() => {
                 if !for_deref || super::should_render_item(item, deref_mut, tcx) {
                     Some(Link::new(
-                        get_next_url(used_links, format!("{}.{}", ItemType::Method, name)),
+                        get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::Method)),
                         name.as_str(),
                     ))
                 } else {
@@ -549,7 +549,7 @@ fn get_associated_constants<'a>(
         .iter()
         .filter_map(|item| match item.name {
             Some(ref name) if !name.is_empty() && item.is_associated_const() => Some(Link::new(
-                get_next_url(used_links, format!("{}.{}", ItemType::AssocConst, name)),
+                get_next_url(used_links, format!("{typ}.{name}", typ = ItemType::AssocConst)),
                 name.as_str(),
             )),
             _ => None,
diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs
index 3f41765a5af..e824651e727 100644
--- a/src/librustdoc/html/render/write_shared.rs
+++ b/src/librustdoc/html/render/write_shared.rs
@@ -73,7 +73,7 @@ pub(super) fn write_shared(
         }
 
         let bytes = try_err!(fs::read(&entry.path), &entry.path);
-        let filename = format!("{}{}.{}", theme, cx.shared.resource_suffix, extension);
+        let filename = format!("{theme}{suffix}.{extension}", suffix = cx.shared.resource_suffix);
         cx.shared.fs.write(cx.dst.join(filename), bytes)?;
     }
 
@@ -112,7 +112,7 @@ pub(super) fn write_shared(
         let mut krates = Vec::new();
 
         if path.exists() {
-            let prefix = format!("\"{}\"", krate);
+            let prefix = format!("\"{krate}\"");
             for line in BufReader::new(File::open(path)?).lines() {
                 let line = line?;
                 if !line.starts_with('"') {
@@ -157,7 +157,7 @@ pub(super) fn write_shared(
         let mut krates = Vec::new();
 
         if path.exists() {
-            let prefix = format!("\"{}\"", krate);
+            let prefix = format!("\"{krate}\"");
             for line in BufReader::new(File::open(path)?).lines() {
                 let line = line?;
                 if !line.starts_with('"') {
@@ -213,10 +213,10 @@ pub(super) fn write_shared(
             let dirs = if subs.is_empty() && files.is_empty() {
                 String::new()
             } else {
-                format!(",[{}]", subs)
+                format!(",[{subs}]")
             };
             let files = files.join(",");
-            let files = if files.is_empty() { String::new() } else { format!(",[{}]", files) };
+            let files = if files.is_empty() { String::new() } else { format!(",[{files}]") };
             format!(
                 "[\"{name}\"{dirs}{files}]",
                 name = self.elem.to_str().expect("invalid osstring conversion"),
@@ -319,8 +319,8 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
     })?;
 
     write_invocation_specific("crates.js", &|| {
-        let krates = krates.iter().map(|k| format!("\"{}\"", k)).join(",");
-        Ok(format!("window.ALL_CRATES = [{}];", krates).into_bytes())
+        let krates = krates.iter().map(|k| format!("\"{k}\"")).join(",");
+        Ok(format!("window.ALL_CRATES = [{krates}];").into_bytes())
     })?;
 
     if options.enable_index_page {
@@ -349,9 +349,8 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
                     .iter()
                     .map(|s| {
                         format!(
-                            "<li><a href=\"{}index.html\">{}</a></li>",
-                            ensure_trailing_slash(s),
-                            s
+                            "<li><a href=\"{trailing_slash}index.html\">{s}</a></li>",
+                            trailing_slash = ensure_trailing_slash(s),
                         )
                     })
                     .collect::<String>()
@@ -444,7 +443,7 @@ if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
             mydst.push(part.to_string());
         }
         cx.shared.ensure_dir(&mydst)?;
-        mydst.push(&format!("{}.{}.js", remote_item_type, remote_path[remote_path.len() - 1]));
+        mydst.push(&format!("{remote_item_type}.{}.js", remote_path[remote_path.len() - 1]));
 
         let (mut all_implementors, _) =
             try_err!(collect(&mydst, krate.name(cx.tcx()).as_str()), &mydst);
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index 3e3fc8a0e72..c4a1ebbec02 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -146,9 +146,8 @@ impl DocVisitor for SourceCollector<'_, '_> {
                     self.cx.shared.tcx.sess.span_err(
                         span,
                         format!(
-                            "failed to render source code for `{}`: {}",
-                            filename.prefer_local(),
-                            e,
+                            "failed to render source code for `{filename}`: {e}",
+                            filename = filename.prefer_local(),
                         ),
                     );
                     false
diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs
index 5d2e4b073c1..a27aa2b58d2 100644
--- a/src/librustdoc/html/static_files.rs
+++ b/src/librustdoc/html/static_files.rs
@@ -53,7 +53,7 @@ pub(crate) fn suffix_path(filename: &str, suffix: &str) -> PathBuf {
     // which would result in `style.min-suffix.css` which isn't what we
     // want.
     let (base, ext) = filename.split_once('.').unwrap();
-    let filename = format!("{}{}.{}", base, suffix, ext);
+    let filename = format!("{base}{suffix}.{ext}");
     filename.into()
 }
 
diff --git a/src/librustdoc/html/templates/STYLE.md b/src/librustdoc/html/templates/STYLE.md
index 0281b1c47f8..38aac2a60e9 100644
--- a/src/librustdoc/html/templates/STYLE.md
+++ b/src/librustdoc/html/templates/STYLE.md
@@ -32,7 +32,7 @@ Askama templates support quite sophisticated control flow. To keep our templates
 simple and understandable, we use only a subset: `if` and `for`. In particular
 we avoid [assignments in the template logic][assignments] and [Askama
 macros][macros]. This also may make things easier if we switch to a different
-Jinja-style template system, like Askama, in the future.
+Jinja-style template system in the future.
 
 [assignments]: https://djc.github.io/askama/template_syntax.html#assignments
 [macros]: https://djc.github.io/askama/template_syntax.html#macros
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index 9392dd4d088..cd791ce000b 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -139,7 +139,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
     fn item(&mut self, item: clean::Item) -> Result<(), Error> {
         let item_type = item.type_();
         let item_name = item.name;
-        trace!("rendering {} {:?}", item_type, item_name);
+        trace!("rendering {item_type} {item_name:?}");
 
         // Flatten items that recursively store other items. We include orphaned items from
         // stripped modules and etc that are otherwise reachable.
@@ -203,11 +203,11 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
                 if !can_be_ignored {
                     assert_eq!(old_item, new_item);
                 }
-                trace!("replaced {:?}\nwith {:?}", old_item, new_item);
+                trace!("replaced {old_item:?}\nwith {new_item:?}");
             }
         }
 
-        trace!("done rendering {} {:?}", item_type, item_name);
+        trace!("done rendering {item_type} {item_name:?}");
         Ok(())
     }
 
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 36d087a7d5b..8220df5d4f3 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -192,8 +192,7 @@ fn init_logging(handler: &EarlyErrorHandler) {
         Ok("never") => false,
         Ok("auto") | Err(VarError::NotPresent) => io::stdout().is_terminal(),
         Ok(value) => handler.early_error(format!(
-            "invalid log color value '{}': expected one of always, never, or auto",
-            value
+            "invalid log color value '{value}': expected one of always, never, or auto",
         )),
         Err(VarError::NotUnicode(value)) => handler.early_error(format!(
             "invalid log color value '{}': expected one of always, never, or auto",
@@ -224,7 +223,7 @@ fn get_args(handler: &EarlyErrorHandler) -> Option<Vec<String>> {
         .map(|(i, arg)| {
             arg.into_string()
                 .map_err(|arg| {
-                    handler.early_warn(format!("Argument {} is not valid Unicode: {:?}", i, arg));
+                    handler.early_warn(format!("Argument {i} is not valid Unicode: {arg:?}"));
                 })
                 .ok()
         })
@@ -665,11 +664,10 @@ fn usage(argv0: &str) {
     for option in opts() {
         (option.apply)(&mut options);
     }
-    println!("{}", options.usage(&format!("{} [options] <input>", argv0)));
+    println!("{}", options.usage(&format!("{argv0} [options] <input>")));
     println!("    @path               Read newline separated options from `path`\n");
     println!(
-        "More information available at {}/rustdoc/what-is-rustdoc.html",
-        DOC_RUST_LANG_ORG_CHANNEL
+        "More information available at {DOC_RUST_LANG_ORG_CHANNEL}/rustdoc/what-is-rustdoc.html",
     );
 }
 
@@ -699,7 +697,7 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>(
                 tcx.sess.struct_err(format!("couldn't generate documentation: {}", e.error));
             let file = e.file.display().to_string();
             if !file.is_empty() {
-                msg.note(format!("failed to create or modify \"{}\"", file));
+                msg.note(format!("failed to create or modify \"{file}\""));
             }
             Err(msg.emit())
         }
diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs
index 749c1ff51bf..d45040e348a 100644
--- a/src/librustdoc/lint.rs
+++ b/src/librustdoc/lint.rs
@@ -185,6 +185,17 @@ declare_rustdoc_lint! {
    "detects unescaped backticks in doc comments"
 }
 
+declare_rustdoc_lint! {
+    /// This lint is **warned by default**. It detects explicit links that are same
+    /// as computed automatic links. This usually means the explicit links is removeable.
+    /// This is a `rustdoc` only lint, see the documentation in the [rustdoc book].
+    ///
+    /// [rustdoc book]: ../../../rustdoc/lints.html#redundant_explicit_links
+    REDUNDANT_EXPLICIT_LINKS,
+    Warn,
+    "detects redundant explicit links in doc comments"
+}
+
 pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
     vec![
         BROKEN_INTRA_DOC_LINKS,
@@ -197,6 +208,7 @@ pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
         BARE_URLS,
         MISSING_CRATE_LEVEL_DOCS,
         UNESCAPED_BACKTICKS,
+        REDUNDANT_EXPLICIT_LINKS,
     ]
 });
 
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index 4321d4aa343..526eea30478 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -43,7 +43,7 @@ pub(crate) fn render<P: AsRef<Path>>(
     edition: Edition,
 ) -> Result<(), String> {
     if let Err(e) = create_dir_all(&options.output) {
-        return Err(format!("{}: {}", options.output.display(), e));
+        return Err(format!("{output}: {e}", output = options.output.display()));
     }
 
     let input = input.as_ref();
@@ -57,11 +57,13 @@ pub(crate) fn render<P: AsRef<Path>>(
             .expect("Writing to a String can't fail");
     }
 
-    let input_str = read_to_string(input).map_err(|err| format!("{}: {}", input.display(), err))?;
+    let input_str =
+        read_to_string(input).map_err(|err| format!("{input}: {err}", input = input.display()))?;
     let playground_url = options.markdown_playground_url.or(options.playground_url);
     let playground = playground_url.map(|url| markdown::Playground { crate_name: None, url });
 
-    let mut out = File::create(&output).map_err(|e| format!("{}: {}", output.display(), e))?;
+    let mut out =
+        File::create(&output).map_err(|e| format!("{output}: {e}", output = output.display()))?;
 
     let (metadata, text) = extract_leading_metadata(&input_str);
     if metadata.is_empty() {
@@ -129,7 +131,7 @@ pub(crate) fn render<P: AsRef<Path>>(
     );
 
     match err {
-        Err(e) => Err(format!("cannot write to `{}`: {}", output.display(), e)),
+        Err(e) => Err(format!("cannot write to `{output}`: {e}", output = output.display())),
         Ok(_) => Ok(()),
     }
 }
@@ -137,7 +139,7 @@ pub(crate) fn render<P: AsRef<Path>>(
 /// Runs any tests/code examples in the markdown file `input`.
 pub(crate) fn test(options: Options) -> Result<(), String> {
     let input_str = read_to_string(&options.input)
-        .map_err(|err| format!("{}: {}", options.input.display(), err))?;
+        .map_err(|err| format!("{input}: {err}", input = options.input.display()))?;
     let mut opts = GlobalTestOptions::default();
     opts.no_crate_inject = true;
     let mut collector = Collector::new(
diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs
index 6ead0cd961a..592dd0a145c 100644
--- a/src/librustdoc/passes/calculate_doc_coverage.rs
+++ b/src/librustdoc/passes/calculate_doc_coverage.rs
@@ -146,8 +146,10 @@ impl<'a, 'b> CoverageCalculator<'a, 'b> {
             examples_percentage: f64,
         ) {
             println!(
-                "| {:<35} | {:>10} | {:>9.1}% | {:>10} | {:>9.1}% |",
-                name, count.with_docs, percentage, count.with_examples, examples_percentage,
+                "| {name:<35} | {with_docs:>10} | {percentage:>9.1}% | {with_examples:>10} | \
+                {examples_percentage:>9.1}% |",
+                with_docs = count.with_docs,
+                with_examples = count.with_examples,
             );
         }
 
@@ -249,7 +251,7 @@ impl<'a, 'b> DocVisitor for CoverageCalculator<'a, 'b> {
 
                 if let Some(span) = i.span(self.ctx.tcx) {
                     let filename = span.filename(self.ctx.sess());
-                    debug!("counting {:?} {:?} in {:?}", i.type_(), i.name, filename);
+                    debug!("counting {:?} {:?} in {filename:?}", i.type_(), i.name);
                     self.items.entry(filename).or_default().count_item(
                         has_docs,
                         has_doc_example,
diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs
index e333a35e8ad..e732a405760 100644
--- a/src/librustdoc/passes/check_doc_test_visibility.rs
+++ b/src/librustdoc/passes/check_doc_test_visibility.rs
@@ -117,7 +117,7 @@ pub(crate) fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item
 
     if tests.found_tests == 0 && cx.tcx.features().rustdoc_missing_doc_code_examples {
         if should_have_doc_example(cx, item) {
-            debug!("reporting error for {:?} (hir_id={:?})", item, hir_id);
+            debug!("reporting error for {item:?} (hir_id={hir_id:?})");
             let sp = item.attr_span(cx.tcx);
             cx.tcx.struct_span_lint_hir(
                 crate::lint::MISSING_DOC_CODE_EXAMPLES,
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 1b8d999024c..36872266ee1 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -150,7 +150,7 @@ impl TryFrom<ResolveRes> for Res {
             PrimTy(prim) => Ok(Res::Primitive(PrimitiveType::from_hir(prim))),
             // e.g. `#[derive]`
             ToolMod | NonMacroAttr(..) | Err => Result::Err(()),
-            other => bug!("unrecognized res {:?}", other),
+            other => bug!("unrecognized res {other:?}"),
         }
     }
 }
@@ -224,7 +224,7 @@ impl UrlFragment {
                             "structfield."
                         }
                     }
-                    kind => bug!("unexpected associated item kind: {:?}", kind),
+                    kind => bug!("unexpected associated item kind: {kind:?}"),
                 };
                 s.push_str(kind);
                 s.push_str(tcx.item_name(def_id).as_str());
@@ -279,7 +279,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
             unresolved: path_str.into(),
         };
 
-        debug!("looking for enum variant {}", path_str);
+        debug!("looking for enum variant {path_str}");
         let mut split = path_str.rsplitn(3, "::");
         let variant_field_name = split
             .next()
@@ -410,7 +410,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
             })
             .and_then(|res| res.try_into().ok())
             .or_else(|| resolve_primitive(path_str, ns));
-        debug!("{} resolved to {:?} in namespace {:?}", path_str, result, ns);
+        debug!("{path_str} resolved to {result:?} in namespace {ns:?}");
         result
     }
 
@@ -453,7 +453,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
             // If there's no `::`, it's not an associated item.
             // So we can be sure that `rustc_resolve` was accurate when it said it wasn't resolved.
             .ok_or_else(|| {
-                debug!("found no `::`, assuming {} was correctly not in scope", item_name);
+                debug!("found no `::`, assuming {item_name} was correctly not in scope");
                 UnresolvedPath {
                     item_id,
                     module_id,
@@ -603,7 +603,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                 def_kind @ (DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::ForeignTy),
                 did,
             ) => {
-                debug!("looking for associated item named {} for item {:?}", item_name, did);
+                debug!("looking for associated item named {item_name} for item {did:?}");
                 // Checks if item_name is a variant of the `SomeItem` enum
                 if ns == TypeNS && def_kind == DefKind::Enum {
                     match tcx.type_of(did).instantiate_identity().kind() {
@@ -651,7 +651,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                     .collect::<Vec<_>>();
                 }
 
-                debug!("got associated item {:?}", assoc_items);
+                debug!("got associated item {assoc_items:?}");
 
                 if !assoc_items.is_empty() {
                     return assoc_items;
@@ -660,7 +660,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> {
                 if ns != Namespace::ValueNS {
                     return Vec::new();
                 }
-                debug!("looking for fields named {} for {:?}", item_name, did);
+                debug!("looking for fields named {item_name} for {did:?}");
                 // FIXME: this doesn't really belong in `associated_item` (maybe `variant_field` is better?)
                 // NOTE: it's different from variant_field because it only resolves struct fields,
                 // not variant fields (2 path segments, not 3).
@@ -727,7 +727,7 @@ fn resolve_associated_trait_item<'a>(
     // Give precedence to inherent impls.
     let traits = trait_impls_for(cx, ty, module);
     let tcx = cx.tcx;
-    debug!("considering traits {:?}", traits);
+    debug!("considering traits {traits:?}");
     let candidates = traits
         .iter()
         .flat_map(|&(impl_, trait_)| {
@@ -744,7 +744,7 @@ fn resolve_associated_trait_item<'a>(
         })
         .collect::<Vec<_>>();
     // FIXME(#74563): warn about ambiguity
-    debug!("the candidates were {:?}", candidates);
+    debug!("the candidates were {candidates:?}");
     candidates
 }
 
@@ -790,10 +790,8 @@ fn trait_impls_for<'a>(
             // Check if these are the same type.
             let impl_type = trait_ref.skip_binder().self_ty();
             trace!(
-                "comparing type {} with kind {:?} against type {:?}",
-                impl_type,
-                impl_type.kind(),
-                ty
+                "comparing type {impl_type} with kind {kind:?} against type {ty:?}",
+                kind = impl_type.kind(),
             );
             // Fast path: if this is a primitive simple `==` will work
             // NOTE: the `match` is necessary; see #92662.
@@ -940,7 +938,7 @@ fn preprocess_link(
     let path_str = match strip_generics_from_path(path_str) {
         Ok(path) => path,
         Err(err) => {
-            debug!("link has malformed generics: {}", path_str);
+            debug!("link has malformed generics: {path_str}");
             return Some(Err(PreprocessingError::MalformedGenerics(err, path_str.to_owned())));
         }
     };
@@ -987,7 +985,7 @@ impl LinkCollector<'_, '_> {
             if !may_have_doc_links(&doc) {
                 continue;
             }
-            debug!("combined_docs={}", doc);
+            debug!("combined_docs={doc}");
             // NOTE: if there are links that start in one crate and end in another, this will not resolve them.
             // This is a degenerate case and it's not supported by rustdoc.
             let item_id = item_id.unwrap_or_else(|| item.item_id.expect_def_id());
@@ -996,7 +994,7 @@ impl LinkCollector<'_, '_> {
                 _ => find_nearest_parent_module(self.cx.tcx, item_id).unwrap(),
             };
             for md_link in preprocessed_markdown_links(&doc) {
-                let link = self.resolve_link(item, item_id, module_id, &doc, &md_link);
+                let link = self.resolve_link(&doc, item, item_id, module_id, &md_link);
                 if let Some(link) = link {
                     self.cx.cache.intra_doc_links.entry(item.item_id).or_default().insert(link);
                 }
@@ -1009,13 +1007,12 @@ impl LinkCollector<'_, '_> {
     /// FIXME(jynelson): this is way too many arguments
     fn resolve_link(
         &mut self,
+        dox: &String,
         item: &Item,
         item_id: DefId,
         module_id: DefId,
-        dox: &str,
-        link: &PreprocessedMarkdownLink,
+        PreprocessedMarkdownLink(pp_link, ori_link): &PreprocessedMarkdownLink,
     ) -> Option<ItemLink> {
-        let PreprocessedMarkdownLink(pp_link, ori_link) = link;
         trace!("considering link '{}'", ori_link.link);
 
         let diag_info = DiagnosticInfo {
@@ -1024,7 +1021,6 @@ impl LinkCollector<'_, '_> {
             ori_link: &ori_link.link,
             link_range: ori_link.range.clone(),
         };
-
         let PreprocessingInfo { path_str, disambiguator, extra_fragment, link_text } =
             pp_link.as_ref().map_err(|err| err.report(self.cx, diag_info.clone())).ok()?;
         let disambiguator = *disambiguator;
@@ -1042,8 +1038,24 @@ impl LinkCollector<'_, '_> {
             // resolutions are cached, for other links we want to report an error every
             // time so they are not cached.
             matches!(ori_link.kind, LinkType::Reference | LinkType::Shortcut),
+            false,
         )?;
 
+        if ori_link.display_text.is_some() {
+            self.resolve_display_text(
+                path_str,
+                ResolutionInfo {
+                    item_id,
+                    module_id,
+                    dis: disambiguator,
+                    path_str: ori_link.display_text.clone()?.into_boxed_str(),
+                    extra_fragment: extra_fragment.clone(),
+                },
+                &ori_link,
+                &diag_info,
+            );
+        }
+
         // Check for a primitive which might conflict with a module
         // Report the ambiguity and require that the user specify which one they meant.
         // FIXME: could there ever be a primitive not in the type namespace?
@@ -1130,10 +1142,10 @@ impl LinkCollector<'_, '_> {
         item: &Item,
         diag_info: &DiagnosticInfo<'_>,
     ) -> Option<()> {
-        debug!("intra-doc link to {} resolved to {:?}", path_str, (kind, id));
+        debug!("intra-doc link to {path_str} resolved to {:?}", (kind, id));
 
         // Disallow e.g. linking to enums with `struct@`
-        debug!("saw kind {:?} with disambiguator {:?}", kind, disambiguator);
+        debug!("saw kind {kind:?} with disambiguator {disambiguator:?}");
         match (kind, disambiguator) {
                 | (DefKind::Const | DefKind::ConstParam | DefKind::AssocConst | DefKind::AnonConst, Some(Disambiguator::Kind(DefKind::Const)))
                 // NOTE: this allows 'method' to mean both normal functions and associated functions
@@ -1174,7 +1186,7 @@ impl LinkCollector<'_, '_> {
         diag_info: &DiagnosticInfo<'_>,
     ) {
         // The resolved item did not match the disambiguator; give a better error than 'not found'
-        let msg = format!("incompatible link kind for `{}`", path_str);
+        let msg = format!("incompatible link kind for `{path_str}`");
         let callback = |diag: &mut Diagnostic, sp: Option<rustc_span::Span>, link_range| {
             let note = format!(
                 "this link resolved to {} {}, which is not {} {}",
@@ -1223,6 +1235,9 @@ impl LinkCollector<'_, '_> {
         // If errors are cached then they are only reported on first occurrence
         // which we want in some cases but not in others.
         cache_errors: bool,
+        // If this call is intended to be recoverable, then pass true to silence.
+        // This is only recoverable when path is failed to resolved.
+        recoverable: bool,
     ) -> Option<(Res, Option<UrlFragment>)> {
         if let Some(res) = self.visited_links.get(&key) {
             if res.is_some() || cache_errors {
@@ -1230,7 +1245,7 @@ impl LinkCollector<'_, '_> {
             }
         }
 
-        let mut candidates = self.resolve_with_disambiguator(&key, diag.clone());
+        let mut candidates = self.resolve_with_disambiguator(&key, diag.clone(), recoverable);
 
         // FIXME: it would be nice to check that the feature gate was enabled in the original crate, not just ignore it altogether.
         // However I'm not sure how to check that across crates.
@@ -1281,6 +1296,9 @@ impl LinkCollector<'_, '_> {
         &mut self,
         key: &ResolutionInfo,
         diag: DiagnosticInfo<'_>,
+        // If this call is intended to be recoverable, then pass true to silence.
+        // This is only recoverable when path is failed to resolved.
+        recoverable: bool,
     ) -> Vec<(Res, Option<DefId>)> {
         let disambiguator = key.dis;
         let path_str = &key.path_str;
@@ -1310,7 +1328,9 @@ impl LinkCollector<'_, '_> {
                                 }
                             }
                         }
-                        resolution_failure(self, diag, path_str, disambiguator, smallvec![err]);
+                        if !recoverable {
+                            resolution_failure(self, diag, path_str, disambiguator, smallvec![err]);
+                        }
                         return vec![];
                     }
                 }
@@ -1347,13 +1367,15 @@ impl LinkCollector<'_, '_> {
                     .fold(0, |acc, res| if let Ok(res) = res { acc + res.len() } else { acc });
 
                 if len == 0 {
-                    resolution_failure(
-                        self,
-                        diag,
-                        path_str,
-                        disambiguator,
-                        candidates.into_iter().filter_map(|res| res.err()).collect(),
-                    );
+                    if !recoverable {
+                        resolution_failure(
+                            self,
+                            diag,
+                            path_str,
+                            disambiguator,
+                            candidates.into_iter().filter_map(|res| res.err()).collect(),
+                        );
+                    }
                     return vec![];
                 } else if len == 1 {
                     candidates.into_iter().filter_map(|res| res.ok()).flatten().collect::<Vec<_>>()
@@ -1374,6 +1396,63 @@ impl LinkCollector<'_, '_> {
             }
         }
     }
+
+    /// Resolve display text if the provided link has separated parts of links.
+    ///
+    /// For example:
+    /// Inline link `[display_text](dest_link)` and reference link `[display_text][reference_link]` has
+    /// separated parts of links.
+    fn resolve_display_text(
+        &mut self,
+        explicit_link: &Box<str>,
+        display_res_info: ResolutionInfo,
+        ori_link: &MarkdownLink,
+        diag_info: &DiagnosticInfo<'_>,
+    ) {
+        // Check if explicit resolution's path is same as resolution of original link's display text path, see
+        // tests/rustdoc-ui/lint/redundant_explicit_links.rs for more cases.
+        //
+        // To avoid disambiguator from panicking, we check if display text path is possible to be disambiguated
+        // into explicit path.
+        if !matches!(
+            ori_link.kind,
+            LinkType::Inline | LinkType::Reference | LinkType::ReferenceUnknown
+        ) {
+            return;
+        }
+
+        // Algorithm to check if display text could possibly be the explicit link:
+        //
+        // Consider 2 links which are display text and explicit link, pick the shorter
+        // one as symbol and longer one as full qualified path, and tries to match symbol
+        // to the full qualified path's last symbol.
+        //
+        // Otherwise, check if 2 links are same, if so, skip the resolve process.
+        //
+        // Notice that this algorithm is passive, might possibly miss actual redudant cases.
+        let explicit_link = &explicit_link.to_string();
+        let display_text = ori_link.display_text.as_ref().unwrap();
+        let display_len = display_text.len();
+        let explicit_len = explicit_link.len();
+
+        if display_len == explicit_len {
+            // Whether they are same or not, skip the resolve process.
+            return;
+        }
+
+        if (explicit_len >= display_len
+            && &explicit_link[(explicit_len - display_len)..] == display_text)
+            || (display_len >= explicit_len
+                && &display_text[(display_len - explicit_len)..] == explicit_link)
+        {
+            self.resolve_with_disambiguator_cached(
+                display_res_info,
+                diag_info.clone(), // this struct should really be Copy, but Range is not :(
+                false,
+                true,
+            );
+        }
+    }
 }
 
 /// Get the section of a link between the backticks,
@@ -1459,7 +1538,7 @@ impl Disambiguator {
                 "value" => NS(Namespace::ValueNS),
                 "macro" => NS(Namespace::MacroNS),
                 "prim" | "primitive" => Primitive,
-                _ => return Err((format!("unknown disambiguator `{}`", prefix), 0..idx)),
+                _ => return Err((format!("unknown disambiguator `{prefix}`"), 0..idx)),
             };
             Ok(Some((d, &rest[1..], &rest[1..])))
         } else {
@@ -1527,7 +1606,7 @@ enum Suggestion {
 impl Suggestion {
     fn descr(&self) -> Cow<'static, str> {
         match self {
-            Self::Prefix(x) => format!("prefix with `{}@`", x).into(),
+            Self::Prefix(x) => format!("prefix with `{x}@`").into(),
             Self::Function => "add parentheses".into(),
             Self::Macro => "add an exclamation mark".into(),
             Self::RemoveDisambiguator => "remove the disambiguator".into(),
@@ -1537,9 +1616,9 @@ impl Suggestion {
     fn as_help(&self, path_str: &str) -> String {
         // FIXME: if this is an implied shortcut link, it's bad style to suggest `@`
         match self {
-            Self::Prefix(prefix) => format!("{}@{}", prefix, path_str),
-            Self::Function => format!("{}()", path_str),
-            Self::Macro => format!("{}!", path_str),
+            Self::Prefix(prefix) => format!("{prefix}@{path_str}"),
+            Self::Function => format!("{path_str}()"),
+            Self::Macro => format!("{path_str}!"),
             Self::RemoveDisambiguator => path_str.into(),
         }
     }
@@ -1574,7 +1653,7 @@ impl Suggestion {
         match self {
             Self::Prefix(prefix) => {
                 // FIXME: if this is an implied shortcut link, it's bad style to suggest `@`
-                let mut sugg = vec![(sp.with_hi(inner_sp.lo()), format!("{}@", prefix))];
+                let mut sugg = vec![(sp.with_hi(inner_sp.lo()), format!("{prefix}@"))];
                 if sp.hi() != inner_sp.hi() {
                     sugg.push((inner_sp.shrink_to_hi().with_hi(sp.hi()), String::new()));
                 }
@@ -1618,7 +1697,7 @@ fn report_diagnostic(
 ) {
     let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id) else {
         // If non-local, no need to check anything.
-        info!("ignoring warning from parent crate: {}", msg);
+        info!("ignoring warning from parent crate: {msg}");
         return;
     };
 
@@ -1696,15 +1775,14 @@ fn resolution_failure(
     report_diagnostic(
         tcx,
         BROKEN_INTRA_DOC_LINKS,
-        format!("unresolved link to `{}`", path_str),
+        format!("unresolved link to `{path_str}`"),
         &diag_info,
         |diag, sp, link_range| {
-            let item = |res: Res| format!("the {} `{}`", res.descr(), res.name(tcx),);
+            let item = |res: Res| format!("the {} `{}`", res.descr(), res.name(tcx));
             let assoc_item_not_allowed = |res: Res| {
                 let name = res.name(tcx);
                 format!(
-                    "`{}` is {} {}, not a module or type, and cannot have associated items",
-                    name,
+                    "`{name}` is {} {}, not a module or type, and cannot have associated items",
                     res.article(),
                     res.descr()
                 )
@@ -1750,7 +1828,7 @@ fn resolution_failure(
                         name = start;
                         for ns in [TypeNS, ValueNS, MacroNS] {
                             if let Ok(v_res) = collector.resolve(start, ns, item_id, module_id) {
-                                debug!("found partial_res={:?}", v_res);
+                                debug!("found partial_res={v_res:?}");
                                 if !v_res.is_empty() {
                                     *partial_res = Some(full_res(tcx, v_res[0]));
                                     *unresolved = end.into();
@@ -1771,10 +1849,10 @@ fn resolution_failure(
                         let note = if partial_res.is_some() {
                             // Part of the link resolved; e.g. `std::io::nonexistent`
                             let module_name = tcx.item_name(module);
-                            format!("no item named `{}` in module `{}`", unresolved, module_name)
+                            format!("no item named `{unresolved}` in module `{module_name}`")
                         } else {
                             // None of the link resolved; e.g. `Notimported`
-                            format!("no item named `{}` in scope", unresolved)
+                            format!("no item named `{unresolved}` in scope")
                         };
                         if let Some(span) = sp {
                             diag.span_label(span, note);
@@ -1879,11 +1957,9 @@ fn resolution_failure(
                     };
                     let name = res.name(tcx);
                     let note = format!(
-                        "the {} `{}` has no {} named `{}`",
-                        res.descr(),
-                        name,
-                        disambiguator.map_or(path_description, |d| d.descr()),
-                        unresolved,
+                        "the {res} `{name}` has no {disamb_res} named `{unresolved}`",
+                        res = res.descr(),
+                        disamb_res = disambiguator.map_or(path_description, |d| d.descr()),
                     );
                     if let Some(span) = sp {
                         diag.span_label(span, note);
@@ -1978,7 +2054,7 @@ fn report_malformed_generics(
     report_diagnostic(
         cx.tcx,
         BROKEN_INTRA_DOC_LINKS,
-        format!("unresolved link to `{}`", path_str),
+        format!("unresolved link to `{path_str}`"),
         &diag_info,
         |diag, sp, _link_range| {
             let note = match err {
@@ -2030,7 +2106,7 @@ fn ambiguity_error(
         return false;
     }
 
-    let mut msg = format!("`{}` is ", path_str);
+    let mut msg = format!("`{path_str}` is ");
     match kinds.as_slice() {
         [res1, res2] => {
             msg += &format!(
@@ -2094,7 +2170,7 @@ fn suggest_disambiguator(
             diag.span_suggestion_verbose(sp, help, suggestion_text, Applicability::MaybeIncorrect);
         }
     } else {
-        diag.help(format!("{}: {}", help, suggestion.as_help(path_str)));
+        diag.help(format!("{help}: {}", suggestion.as_help(path_str)));
     }
 }
 
@@ -2108,8 +2184,7 @@ fn privacy_error(cx: &DocContext<'_>, diag_info: &DiagnosticInfo<'_>, path_str:
         }
         None => "<unknown>",
     };
-    let msg =
-        format!("public documentation for `{}` links to private item `{}`", item_name, path_str);
+    let msg = format!("public documentation for `{item_name}` links to private item `{path_str}`");
 
     report_diagnostic(cx.tcx, PRIVATE_INTRA_DOC_LINKS, msg, diag_info, |diag, sp, _link_range| {
         if let Some(sp) = sp {
@@ -2160,6 +2235,6 @@ fn resolve_primitive(path_str: &str, ns: Namespace) -> Option<Res> {
         "never" | "!" => Never,
         _ => return None,
     };
-    debug!("resolved primitives {:?}", prim);
+    debug!("resolved primitives {prim:?}");
     Some(Res::Primitive(prim))
 }
diff --git a/src/librustdoc/passes/lint.rs b/src/librustdoc/passes/lint.rs
index e653207b9b6..c6d5b7bd346 100644
--- a/src/librustdoc/passes/lint.rs
+++ b/src/librustdoc/passes/lint.rs
@@ -4,6 +4,7 @@
 mod bare_urls;
 mod check_code_block_syntax;
 mod html_tags;
+mod redundant_explicit_links;
 mod unescaped_backticks;
 
 use super::Pass;
@@ -29,6 +30,7 @@ impl<'a, 'tcx> DocVisitor for Linter<'a, 'tcx> {
         check_code_block_syntax::visit_item(self.cx, item);
         html_tags::visit_item(self.cx, item);
         unescaped_backticks::visit_item(self.cx, item);
+        redundant_explicit_links::visit_item(self.cx, item);
 
         self.visit_item_recur(item)
     }
diff --git a/src/librustdoc/passes/lint/bare_urls.rs b/src/librustdoc/passes/lint/bare_urls.rs
index 5658b31d9bb..97078a5cb16 100644
--- a/src/librustdoc/passes/lint/bare_urls.rs
+++ b/src/librustdoc/passes/lint/bare_urls.rs
@@ -28,7 +28,7 @@ pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item) {
                         .span_suggestion(
                             sp,
                             "use an automatic link instead",
-                            format!("<{}>", url),
+                            format!("<{url}>"),
                             Applicability::MachineApplicable,
                         )
                 });
@@ -74,7 +74,7 @@ fn find_raw_urls(
     range: Range<usize>,
     f: &impl Fn(&DocContext<'_>, &'static str, &str, Range<usize>),
 ) {
-    trace!("looking for raw urls in {}", text);
+    trace!("looking for raw urls in {text}");
     // For now, we only check "full" URLs (meaning, starting with "http://" or "https://").
     for match_ in URL_REGEX.find_iter(text) {
         let url = match_.as_str();
diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs
index 8e5ee382c86..37e28e1fbca 100644
--- a/src/librustdoc/passes/lint/check_code_block_syntax.rs
+++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs
@@ -107,7 +107,7 @@ fn check_rust_syntax(
                 // just give a `help` instead.
                 lint.span_help(
                     sp.from_inner(InnerSpan::new(0, 3)),
-                    format!("{}: ```text", explanation),
+                    format!("{explanation}: ```text"),
                 );
             } else if empty_block {
                 lint.span_suggestion(
@@ -118,7 +118,7 @@ fn check_rust_syntax(
                 );
             }
         } else if empty_block || is_ignore {
-            lint.help(format!("{}: ```text", explanation));
+            lint.help(format!("{explanation}: ```text"));
         }
 
         // FIXME(#67563): Provide more context for these errors by displaying the spans inline.
@@ -160,7 +160,7 @@ impl Emitter for BufferEmitter {
             .translate_message(&diag.message[0].0, &fluent_args)
             .unwrap_or_else(|e| panic!("{e}"));
 
-        buffer.messages.push(format!("error from rustc: {}", translated_main_message));
+        buffer.messages.push(format!("error from rustc: {translated_main_message}"));
         if diag.is_error() {
             buffer.has_errors = true;
         }
diff --git a/src/librustdoc/passes/lint/html_tags.rs b/src/librustdoc/passes/lint/html_tags.rs
index 24f452b216c..c135c584cec 100644
--- a/src/librustdoc/passes/lint/html_tags.rs
+++ b/src/librustdoc/passes/lint/html_tags.rs
@@ -155,7 +155,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
             let t = t.to_lowercase();
             !ALLOWED_UNCLOSED.contains(&t.as_str())
         }) {
-            report_diag(format!("unclosed HTML tag `{}`", tag), range, true);
+            report_diag(format!("unclosed HTML tag `{tag}`"), range, true);
         }
 
         if let Some(range) = is_in_comment {
@@ -194,14 +194,14 @@ fn drop_tag(
             // `tags` is used as a queue, meaning that everything after `pos` is included inside it.
             // So `<h2><h3></h2>` will look like `["h2", "h3"]`. So when closing `h2`, we will still
             // have `h3`, meaning the tag wasn't closed as it should have.
-            f(format!("unclosed HTML tag `{}`", last_tag_name), &last_tag_span, true);
+            f(format!("unclosed HTML tag `{last_tag_name}`"), &last_tag_span, true);
         }
         // Remove the `tag_name` that was originally closed
         tags.pop();
     } else {
         // It can happen for example in this case: `<h2></script></h2>` (the `h2` tag isn't required
         // but it helps for the visualization).
-        f(format!("unopened HTML tag `{}`", tag_name), &range, false);
+        f(format!("unopened HTML tag `{tag_name}`"), &range, false);
     }
 }
 
@@ -355,7 +355,7 @@ fn extract_html_tag(
                     if let Some(quote_pos) = quote_pos {
                         let qr = Range { start: quote_pos, end: quote_pos };
                         f(
-                            format!("unclosed quoted HTML attribute on tag `{}`", tag_name),
+                            format!("unclosed quoted HTML attribute on tag `{tag_name}`"),
                             &qr,
                             false,
                         );
@@ -368,7 +368,7 @@ fn extract_html_tag(
                                 at == "svg" || at == "math"
                             });
                         if !valid {
-                            f(format!("invalid self-closing HTML tag `{}`", tag_name), &r, false);
+                            f(format!("invalid self-closing HTML tag `{tag_name}`"), &r, false);
                         }
                     } else {
                         tags.push((tag_name, r));
diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs
new file mode 100644
index 00000000000..ef0f8716aa8
--- /dev/null
+++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs
@@ -0,0 +1,352 @@
+use std::ops::Range;
+
+use pulldown_cmark::{BrokenLink, CowStr, Event, LinkType, OffsetIter, Parser, Tag};
+use rustc_ast::NodeId;
+use rustc_errors::SuggestionStyle;
+use rustc_hir::def::{DefKind, DocLinkResMap, Namespace, Res};
+use rustc_hir::HirId;
+use rustc_lint_defs::Applicability;
+use rustc_span::Symbol;
+
+use crate::clean::utils::find_nearest_parent_module;
+use crate::clean::utils::inherits_doc_hidden;
+use crate::clean::Item;
+use crate::core::DocContext;
+use crate::html::markdown::main_body_opts;
+use crate::passes::source_span_for_markdown_range;
+
+#[derive(Debug)]
+struct LinkData {
+    resolvable_link: Option<String>,
+    resolvable_link_range: Option<Range<usize>>,
+    display_link: String,
+}
+
+pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
+    let Some(hir_id) = DocContext::as_local_hir_id(cx.tcx, item.item_id) else {
+        // If non-local, no need to check anything.
+        return;
+    };
+
+    let doc = item.doc_value();
+    if doc.is_empty() {
+        return;
+    }
+
+    if item.link_names(&cx.cache).is_empty() {
+        // If there's no link names in this item,
+        // then we skip resolution querying to
+        // avoid from panicking.
+        return;
+    }
+
+    let Some(item_id) = item.def_id() else {
+        return;
+    };
+    let Some(local_item_id) = item_id.as_local() else {
+        return;
+    };
+
+    let is_hidden = !cx.render_options.document_hidden
+        && (item.is_doc_hidden() || inherits_doc_hidden(cx.tcx, local_item_id, None));
+    if is_hidden {
+        return;
+    }
+    let is_private = !cx.render_options.document_private
+        && !cx.cache.effective_visibilities.is_directly_public(cx.tcx, item_id);
+    if is_private {
+        return;
+    }
+
+    check_redundant_explicit_link(cx, item, hir_id, &doc);
+}
+
+fn check_redundant_explicit_link<'md>(
+    cx: &DocContext<'_>,
+    item: &Item,
+    hir_id: HirId,
+    doc: &'md str,
+) -> Option<()> {
+    let mut broken_line_callback = |link: BrokenLink<'md>| Some((link.reference, "".into()));
+    let mut offset_iter = Parser::new_with_broken_link_callback(
+        &doc,
+        main_body_opts(),
+        Some(&mut broken_line_callback),
+    )
+    .into_offset_iter();
+    let item_id = item.def_id()?;
+    let module_id = match cx.tcx.def_kind(item_id) {
+        DefKind::Mod if item.inner_docs(cx.tcx) => item_id,
+        _ => find_nearest_parent_module(cx.tcx, item_id).unwrap(),
+    };
+    let resolutions = cx.tcx.doc_link_resolutions(module_id);
+
+    while let Some((event, link_range)) = offset_iter.next() {
+        match event {
+            Event::Start(Tag::Link(link_type, dest, _)) => {
+                let link_data = collect_link_data(&mut offset_iter);
+
+                if let Some(resolvable_link) = link_data.resolvable_link.as_ref() {
+                    if &link_data.display_link.replace("`", "") != resolvable_link {
+                        // Skips if display link does not match to actual
+                        // resolvable link, usually happens if display link
+                        // has several segments, e.g.
+                        // [this is just an `Option`](Option)
+                        continue;
+                    }
+                }
+
+                let explicit_link = dest.to_string();
+                let display_link = link_data.resolvable_link.clone()?;
+                let explicit_len = explicit_link.len();
+                let display_len = display_link.len();
+
+                if (explicit_len >= display_len
+                    && &explicit_link[(explicit_len - display_len)..] == display_link)
+                    || (display_len >= explicit_len
+                        && &display_link[(display_len - explicit_len)..] == explicit_link)
+                {
+                    match link_type {
+                        LinkType::Inline | LinkType::ReferenceUnknown => {
+                            check_inline_or_reference_unknown_redundancy(
+                                cx,
+                                item,
+                                hir_id,
+                                doc,
+                                resolutions,
+                                link_range,
+                                dest.to_string(),
+                                link_data,
+                                if link_type == LinkType::Inline {
+                                    (b'(', b')')
+                                } else {
+                                    (b'[', b']')
+                                },
+                            );
+                        }
+                        LinkType::Reference => {
+                            check_reference_redundancy(
+                                cx,
+                                item,
+                                hir_id,
+                                doc,
+                                resolutions,
+                                link_range,
+                                &dest,
+                                link_data,
+                            );
+                        }
+                        _ => {}
+                    }
+                }
+            }
+            _ => {}
+        }
+    }
+
+    None
+}
+
+/// FIXME(ChAoSUnItY): Too many arguments.
+fn check_inline_or_reference_unknown_redundancy(
+    cx: &DocContext<'_>,
+    item: &Item,
+    hir_id: HirId,
+    doc: &str,
+    resolutions: &DocLinkResMap,
+    link_range: Range<usize>,
+    dest: String,
+    link_data: LinkData,
+    (open, close): (u8, u8),
+) -> Option<()> {
+    let (resolvable_link, resolvable_link_range) =
+        (&link_data.resolvable_link?, &link_data.resolvable_link_range?);
+    let (dest_res, display_res) =
+        (find_resolution(resolutions, &dest)?, find_resolution(resolutions, resolvable_link)?);
+
+    if dest_res == display_res {
+        let link_span = source_span_for_markdown_range(cx.tcx, &doc, &link_range, &item.attrs)
+            .unwrap_or(item.attr_span(cx.tcx));
+        let explicit_span = source_span_for_markdown_range(
+            cx.tcx,
+            &doc,
+            &offset_explicit_range(doc, link_range, open, close),
+            &item.attrs,
+        )?;
+        let display_span =
+            source_span_for_markdown_range(cx.tcx, &doc, &resolvable_link_range, &item.attrs)?;
+
+        cx.tcx.struct_span_lint_hir(crate::lint::REDUNDANT_EXPLICIT_LINKS, hir_id, explicit_span, "redundant explicit link target", |lint| {
+            lint.span_label(explicit_span, "explicit target is redundant")
+                .span_label(display_span, "because label contains path that resolves to same destination")
+                .note("when a link's destination is not specified,\nthe label is used to resolve intra-doc links")
+                .span_suggestion_with_style(link_span, "remove explicit link target", format!("[{}]", link_data.display_link), Applicability::MaybeIncorrect, SuggestionStyle::ShowAlways);
+
+            lint
+        });
+    }
+
+    None
+}
+
+/// FIXME(ChAoSUnItY): Too many arguments.
+fn check_reference_redundancy(
+    cx: &DocContext<'_>,
+    item: &Item,
+    hir_id: HirId,
+    doc: &str,
+    resolutions: &DocLinkResMap,
+    link_range: Range<usize>,
+    dest: &CowStr<'_>,
+    link_data: LinkData,
+) -> Option<()> {
+    let (resolvable_link, resolvable_link_range) =
+        (&link_data.resolvable_link?, &link_data.resolvable_link_range?);
+    let (dest_res, display_res) =
+        (find_resolution(resolutions, &dest)?, find_resolution(resolutions, resolvable_link)?);
+
+    if dest_res == display_res {
+        let link_span = source_span_for_markdown_range(cx.tcx, &doc, &link_range, &item.attrs)
+            .unwrap_or(item.attr_span(cx.tcx));
+        let explicit_span = source_span_for_markdown_range(
+            cx.tcx,
+            &doc,
+            &offset_explicit_range(doc, link_range.clone(), b'[', b']'),
+            &item.attrs,
+        )?;
+        let display_span =
+            source_span_for_markdown_range(cx.tcx, &doc, &resolvable_link_range, &item.attrs)?;
+        let def_span = source_span_for_markdown_range(
+            cx.tcx,
+            &doc,
+            &offset_reference_def_range(doc, dest, link_range),
+            &item.attrs,
+        )?;
+
+        cx.tcx.struct_span_lint_hir(crate::lint::REDUNDANT_EXPLICIT_LINKS, hir_id, explicit_span, "redundant explicit link target", |lint| {
+            lint.span_label(explicit_span, "explicit target is redundant")
+                .span_label(display_span, "because label contains path that resolves to same destination")
+                .span_note(def_span, "referenced explicit link target defined here")
+                .note("when a link's destination is not specified,\nthe label is used to resolve intra-doc links")
+                .span_suggestion_with_style(link_span, "remove explicit link target", format!("[{}]", link_data.display_link), Applicability::MaybeIncorrect, SuggestionStyle::ShowAlways);
+
+            lint
+        });
+    }
+
+    None
+}
+
+fn find_resolution(resolutions: &DocLinkResMap, path: &str) -> Option<Res<NodeId>> {
+    [Namespace::TypeNS, Namespace::ValueNS, Namespace::MacroNS]
+        .into_iter()
+        .find_map(|ns| resolutions.get(&(Symbol::intern(path), ns)).copied().flatten())
+}
+
+/// Collects all neccessary data of link.
+fn collect_link_data(offset_iter: &mut OffsetIter<'_, '_>) -> LinkData {
+    let mut resolvable_link = None;
+    let mut resolvable_link_range = None;
+    let mut display_link = String::new();
+
+    while let Some((event, range)) = offset_iter.next() {
+        match event {
+            Event::Text(code) => {
+                let code = code.to_string();
+                display_link.push_str(&code);
+                resolvable_link = Some(code);
+                resolvable_link_range = Some(range);
+            }
+            Event::Code(code) => {
+                let code = code.to_string();
+                display_link.push('`');
+                display_link.push_str(&code);
+                display_link.push('`');
+                resolvable_link = Some(code);
+                resolvable_link_range = Some(range);
+            }
+            Event::End(_) => {
+                break;
+            }
+            _ => {}
+        }
+    }
+
+    LinkData { resolvable_link, resolvable_link_range, display_link }
+}
+
+fn offset_explicit_range(md: &str, link_range: Range<usize>, open: u8, close: u8) -> Range<usize> {
+    let mut open_brace = !0;
+    let mut close_brace = !0;
+    for (i, b) in md.as_bytes()[link_range.clone()].iter().copied().enumerate().rev() {
+        let i = i + link_range.start;
+        if b == close {
+            close_brace = i;
+            break;
+        }
+    }
+
+    if close_brace < link_range.start || close_brace >= link_range.end {
+        return link_range;
+    }
+
+    let mut nesting = 1;
+
+    for (i, b) in md.as_bytes()[link_range.start..close_brace].iter().copied().enumerate().rev() {
+        let i = i + link_range.start;
+        if b == close {
+            nesting += 1;
+        }
+        if b == open {
+            nesting -= 1;
+        }
+        if nesting == 0 {
+            open_brace = i;
+            break;
+        }
+    }
+
+    assert!(open_brace != close_brace);
+
+    if open_brace < link_range.start || open_brace >= link_range.end {
+        return link_range;
+    }
+    // do not actually include braces in the span
+    (open_brace + 1)..close_brace
+}
+
+fn offset_reference_def_range(
+    md: &str,
+    dest: &CowStr<'_>,
+    link_range: Range<usize>,
+) -> Range<usize> {
+    // For diagnostics, we want to underline the link's definition but `span` will point at
+    // where the link is used. This is a problem for reference-style links, where the definition
+    // is separate from the usage.
+
+    match dest {
+        // `Borrowed` variant means the string (the link's destination) may come directly from
+        // the markdown text and we can locate the original link destination.
+        // NOTE: LinkReplacer also provides `Borrowed` but possibly from other sources,
+        // so `locate()` can fall back to use `span`.
+        CowStr::Borrowed(s) => {
+            // FIXME: remove this function once pulldown_cmark can provide spans for link definitions.
+            unsafe {
+                let s_start = dest.as_ptr();
+                let s_end = s_start.add(s.len());
+                let md_start = md.as_ptr();
+                let md_end = md_start.add(md.len());
+                if md_start <= s_start && s_end <= md_end {
+                    let start = s_start.offset_from(md_start) as usize;
+                    let end = s_end.offset_from(md_start) as usize;
+                    start..end
+                } else {
+                    link_range
+                }
+            }
+        }
+
+        // For anything else, we can only use the provided range.
+        CowStr::Boxed(_) | CowStr::Inlined(_) => link_range,
+    }
+}
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index 647d8358840..534c6eebbdd 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -255,7 +255,7 @@ where
                 let fn_key = tcx.def_path_hash(*def_id);
                 let fn_entries = self.calls.entry(fn_key).or_default();
 
-                trace!("Including expr: {:?}", call_span);
+                trace!("Including expr: {call_span:?}");
                 let enclosing_item_span =
                     source_map.span_extend_to_prev_char(enclosing_item_span, '\n', false);
                 let location =
@@ -345,7 +345,7 @@ pub(crate) fn load_call_locations(
     let inner = || {
         let mut all_calls: AllCallLocations = FxHashMap::default();
         for path in with_examples {
-            let bytes = fs::read(&path).map_err(|e| format!("{} (for path {})", e, path))?;
+            let bytes = fs::read(&path).map_err(|e| format!("{e} (for path {path})"))?;
             let mut decoder = MemDecoder::new(&bytes, 0);
             let calls = AllCallLocations::decode(&mut decoder);
 
@@ -358,7 +358,7 @@ pub(crate) fn load_call_locations(
     };
 
     inner().map_err(|e: String| {
-        diag.err(format!("failed to load examples: {}", e));
+        diag.err(format!("failed to load examples: {e}"));
         1
     })
 }
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 3bad9ba4e4a..549fd67e32a 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -180,7 +180,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
     /// 1. The items which are not glob imports/reexports.
     /// 2. The glob imports/reexports.
     fn visit_mod_contents(&mut self, def_id: LocalDefId, m: &'tcx hir::Mod<'tcx>) {
-        debug!("Going through module {:?}", m);
+        debug!("Going through module {m:?}");
         // Keep track of if there were any private modules in the path.
         let orig_inside_public_path = self.inside_public_path;
         self.inside_public_path &= self.cx.tcx.local_visibility(def_id).is_public();
@@ -203,7 +203,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             }
         }
         self.inside_public_path = orig_inside_public_path;
-        debug!("Leaving module {:?}", m);
+        debug!("Leaving module {m:?}");
     }
 
     /// Tries to resolve the target of a `pub use` statement and inlines the
@@ -394,7 +394,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         renamed: Option<Symbol>,
         import_id: Option<LocalDefId>,
     ) {
-        debug!("visiting item {:?}", item);
+        debug!("visiting item {item:?}");
         if self.inside_body {
             // Only impls can be "seen" outside a body. For example:
             //
diff --git a/src/llvm-project b/src/llvm-project
-Subproject 7c612e1732f3976fcfe29526ad796cbb6174b82
+Subproject 1833c2be108aefcb5d25f6280cf9763b1feb800
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 7c3904d6c3ed54e8a413023519b55a536ad44d5
+Subproject 80eca0e58fb2ff52c1e94fc191b55b37ed73e0e
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
index c634de960d1..7b00eabf97b 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
@@ -5,14 +5,16 @@ use clippy_utils::{get_parent_node, inherits_cfg, is_from_proc_macro, is_self};
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_qpath, FnKind, Visitor};
-use rustc_hir::{Body, ExprKind, FnDecl, HirId, HirIdMap, HirIdSet, Impl, ItemKind, Mutability, Node, PatKind, QPath};
+use rustc_hir::{
+    Body, Closure, Expr, ExprKind, FnDecl, HirId, HirIdMap, HirIdSet, Impl, ItemKind, Mutability, Node, PatKind, QPath,
+};
 use rustc_hir_typeck::expr_use_visitor as euv;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::map::associated_body;
 use rustc_middle::hir::nested_filter::OnlyBodies;
 use rustc_middle::mir::FakeReadCause;
-use rustc_middle::ty::{self, Ty, UpvarId, UpvarPath};
+use rustc_middle::ty::{self, Ty, TyCtxt, UpvarId, UpvarPath};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::kw;
@@ -147,22 +149,36 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
         // Collect variables mutably used and spans which will need dereferencings from the
         // function body.
         let MutablyUsedVariablesCtxt { mutably_used_vars, .. } = {
-            let mut ctx = MutablyUsedVariablesCtxt::default();
+            let mut ctx = MutablyUsedVariablesCtxt {
+                mutably_used_vars: HirIdSet::default(),
+                prev_bind: None,
+                prev_move_to_closure: HirIdSet::default(),
+                aliases: HirIdMap::default(),
+                async_closures: FxHashSet::default(),
+                tcx: cx.tcx,
+            };
             let infcx = cx.tcx.infer_ctxt().build();
             euv::ExprUseVisitor::new(&mut ctx, &infcx, fn_def_id, cx.param_env, cx.typeck_results()).consume_body(body);
             if is_async {
-                let closures = ctx.async_closures.clone();
-                let hir = cx.tcx.hir();
-                for closure in closures {
-                    ctx.prev_bind = None;
-                    ctx.prev_move_to_closure.clear();
-                    if let Some(body) = hir
-                        .find_by_def_id(closure)
-                        .and_then(associated_body)
-                        .map(|(_, body_id)| hir.body(body_id))
-                    {
-                        euv::ExprUseVisitor::new(&mut ctx, &infcx, closure, cx.param_env, cx.typeck_results())
-                            .consume_body(body);
+                let mut checked_closures = FxHashSet::default();
+                while !ctx.async_closures.is_empty() {
+                    let closures = ctx.async_closures.clone();
+                    ctx.async_closures.clear();
+                    let hir = cx.tcx.hir();
+                    for closure in closures {
+                        if !checked_closures.insert(closure) {
+                            continue;
+                        }
+                        ctx.prev_bind = None;
+                        ctx.prev_move_to_closure.clear();
+                        if let Some(body) = hir
+                            .find_by_def_id(closure)
+                            .and_then(associated_body)
+                            .map(|(_, body_id)| hir.body(body_id))
+                        {
+                            euv::ExprUseVisitor::new(&mut ctx, &infcx, closure, cx.param_env, cx.typeck_results())
+                                .consume_body(body);
+                        }
                     }
                 }
             }
@@ -225,16 +241,16 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
     }
 }
 
-#[derive(Default)]
-struct MutablyUsedVariablesCtxt {
+struct MutablyUsedVariablesCtxt<'tcx> {
     mutably_used_vars: HirIdSet,
     prev_bind: Option<HirId>,
     prev_move_to_closure: HirIdSet,
     aliases: HirIdMap<HirId>,
     async_closures: FxHashSet<LocalDefId>,
+    tcx: TyCtxt<'tcx>,
 }
 
-impl MutablyUsedVariablesCtxt {
+impl<'tcx> MutablyUsedVariablesCtxt<'tcx> {
     fn add_mutably_used_var(&mut self, mut used_id: HirId) {
         while let Some(id) = self.aliases.get(&used_id) {
             self.mutably_used_vars.insert(used_id);
@@ -242,9 +258,27 @@ impl MutablyUsedVariablesCtxt {
         }
         self.mutably_used_vars.insert(used_id);
     }
+
+    fn would_be_alias_cycle(&self, alias: HirId, mut target: HirId) -> bool {
+        while let Some(id) = self.aliases.get(&target) {
+            if *id == alias {
+                return true;
+            }
+            target = *id;
+        }
+        false
+    }
+
+    fn add_alias(&mut self, alias: HirId, target: HirId) {
+        // This is to prevent alias loop.
+        if alias == target || self.would_be_alias_cycle(alias, target) {
+            return;
+        }
+        self.aliases.insert(alias, target);
+    }
 }
 
-impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt {
+impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> {
     fn consume(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, _id: HirId) {
         if let euv::Place {
             base:
@@ -259,7 +293,7 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt {
         {
             if let Some(bind_id) = self.prev_bind.take() {
                 if bind_id != *vid {
-                    self.aliases.insert(bind_id, *vid);
+                    self.add_alias(bind_id, *vid);
                 }
             } else if !self.prev_move_to_closure.contains(vid)
                 && matches!(base_ty.ref_mutability(), Some(Mutability::Mut))
@@ -289,6 +323,25 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt {
             {
                 self.add_mutably_used_var(*vid);
             }
+        } else if borrow == ty::ImmBorrow {
+            // If there is an `async block`, it'll contain a call to a closure which we need to
+            // go into to ensure all "mutate" checks are found.
+            if let Node::Expr(Expr {
+                kind:
+                    ExprKind::Call(
+                        _,
+                        [
+                            Expr {
+                                kind: ExprKind::Closure(Closure { def_id, .. }),
+                                ..
+                            },
+                        ],
+                    ),
+                ..
+            }) = self.tcx.hir().get(cmt.hir_id)
+            {
+                self.async_closures.insert(*def_id);
+            }
         }
     }
 
@@ -296,7 +349,12 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt {
         self.prev_bind = None;
         if let euv::Place {
             projections,
-            base: euv::PlaceBase::Local(vid),
+            base:
+                euv::PlaceBase::Local(vid)
+                | euv::PlaceBase::Upvar(UpvarId {
+                    var_path: UpvarPath { hir_id: vid },
+                    ..
+                }),
             ..
         } = &cmt.place
         {
@@ -329,8 +387,9 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt {
                 // Seems like we are inside an async function. We need to store the closure `DefId`
                 // to go through it afterwards.
                 self.async_closures.insert(inner);
-                self.aliases.insert(cmt.hir_id, *vid);
+                self.add_alias(cmt.hir_id, *vid);
                 self.prev_move_to_closure.insert(*vid);
+                self.prev_bind = None;
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
index bd4dc07a42b..5ac4f0aa46c 100644
--- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs
+++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
@@ -5,6 +5,7 @@ use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts};
 use clippy_utils::{get_parent_expr, is_trait_method, is_ty_alias, match_def_path, path_to_local, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{BindingAnnotation, Expr, ExprKind, HirId, MatchSource, Node, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -39,6 +40,7 @@ declare_clippy_lint! {
 #[derive(Default)]
 pub struct UselessConversion {
     try_desugar_arm: Vec<HirId>,
+    expn_depth: u32,
 }
 
 impl_lint_pass!(UselessConversion => [USELESS_CONVERSION]);
@@ -105,6 +107,7 @@ fn into_iter_deep_call<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) -
 impl<'tcx> LateLintPass<'tcx> for UselessConversion {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         if e.span.from_expansion() {
+            self.expn_depth += 1;
             return;
         }
 
@@ -150,9 +153,14 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                 {
                     if let Some(parent) = get_parent_expr(cx, e) {
                         let parent_fn = match parent.kind {
-                            ExprKind::Call(recv, args) if let ExprKind::Path(ref qpath) = recv.kind => {
-                                cx.qpath_res(qpath, recv.hir_id).opt_def_id()
-                                    .map(|did| (did, args, MethodOrFunction::Function))
+                            ExprKind::Call(recv, args)
+                                if let ExprKind::Path(ref qpath) = recv.kind
+                                    && let Some(did) = cx.qpath_res(qpath, recv.hir_id).opt_def_id()
+                                    // make sure that the path indeed points to a fn-like item, so that
+                                    // `fn_sig` does not ICE. (see #11065)
+                                    && cx.tcx.opt_def_kind(did).is_some_and(DefKind::is_fn_like) =>
+                            {
+                                    Some((did, args, MethodOrFunction::Function))
                             }
                             ExprKind::MethodCall(.., args, _) => {
                                 cx.typeck_results().type_dependent_def_id(parent.hir_id)
@@ -168,6 +176,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                             && let Some(&into_iter_param) = sig.inputs().get(kind.param_pos(arg_pos))
                             && let ty::Param(param) = into_iter_param.kind()
                             && let Some(span) = into_iter_bound(cx, parent_fn_did, into_iter_did, param.index)
+                            && self.expn_depth == 0
                         {
                             // Get the "innermost" `.into_iter()` call, e.g. given this expression:
                             // `foo.into_iter().into_iter()`
@@ -303,5 +312,8 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
         if Some(&e.hir_id) == self.try_desugar_arm.last() {
             self.try_desugar_arm.pop();
         }
+        if e.span.from_expansion() {
+            self.expn_depth -= 1;
+        }
     }
 }
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 139e31bc528..43523faa236 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
@@ -291,8 +291,8 @@ fn check_terminator<'tcx>(
         | TerminatorKind::FalseUnwind { .. }
         | TerminatorKind::Goto { .. }
         | TerminatorKind::Return
-        | TerminatorKind::Resume
-        | TerminatorKind::Terminate
+        | TerminatorKind::UnwindResume
+        | TerminatorKind::UnwindTerminate
         | TerminatorKind::Unreachable => Ok(()),
         TerminatorKind::Drop { place, .. } => {
             if !is_ty_const_destruct(tcx, place.ty(&body.local_decls, tcx).ty, body) {
diff --git a/src/tools/clippy/tests/ui/crashes/ice-11065.rs b/src/tools/clippy/tests/ui/crashes/ice-11065.rs
new file mode 100644
index 00000000000..f5cf6b1cd77
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-11065.rs
@@ -0,0 +1,19 @@
+#![warn(clippy::useless_conversion)]
+
+use std::iter::FromIterator;
+use std::option::IntoIter as OptionIter;
+
+fn eq<T: Eq>(a: T, b: T) -> bool {
+    a == b
+}
+
+macro_rules! tests {
+    ($($expr:expr, $ty:ty, ($($test:expr),*);)+) => (pub fn main() {$({
+        const C: $ty = $expr;
+        assert!(eq(C($($test),*), $expr($($test),*)));
+    })+})
+}
+
+tests! {
+    FromIterator::from_iter, fn(OptionIter<i32>) -> Vec<i32>, (Some(5).into_iter());
+}
diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs
index ae7b018d0e2..ec87d447597 100644
--- a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs
+++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs
@@ -196,6 +196,41 @@ mod foo {
     //~| NOTE: this is cfg-gated and may require further changes
 }
 
+// Should not warn.
+async fn inner_async(x: &mut i32, y: &mut u32) {
+    async {
+        *y += 1;
+        *x += 1;
+    }
+    .await;
+}
+
+async fn inner_async2(x: &mut i32, y: &mut u32) {
+    //~^ ERROR: this argument is a mutable reference, but not used mutably
+    async {
+        *x += 1;
+    }
+    .await;
+}
+
+async fn inner_async3(x: &mut i32, y: &mut u32) {
+    //~^ ERROR: this argument is a mutable reference, but not used mutably
+    async {
+        *y += 1;
+    }
+    .await;
+}
+
+// Should not warn.
+async fn async_vec(b: &mut Vec<bool>) {
+    b.append(&mut vec![]);
+}
+
+// Should not warn.
+async fn async_vec2(b: &mut Vec<bool>) {
+    b.push(true);
+}
+
 fn main() {
     let mut u = 0;
     let mut v = vec![0];
diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr
index 0d426ce32f9..2e06e7252d9 100644
--- a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr
+++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr
@@ -94,5 +94,17 @@ LL |     fn cfg_warn(s: &mut u32) {}
    |
    = note: this is cfg-gated and may require further changes
 
-error: aborting due to 15 previous errors
+error: this argument is a mutable reference, but not used mutably
+  --> $DIR/needless_pass_by_ref_mut.rs:208:39
+   |
+LL | async fn inner_async2(x: &mut i32, y: &mut u32) {
+   |                                       ^^^^^^^^ help: consider changing to: `&u32`
+
+error: this argument is a mutable reference, but not used mutably
+  --> $DIR/needless_pass_by_ref_mut.rs:216:26
+   |
+LL | async fn inner_async3(x: &mut i32, y: &mut u32) {
+   |                          ^^^^^^^^ help: consider changing to: `&i32`
+
+error: aborting due to 17 previous errors
 
diff --git a/src/tools/clippy/tests/ui/useless_conversion.fixed b/src/tools/clippy/tests/ui/useless_conversion.fixed
index 5d2c5b11658..53d8a5a9ff1 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.fixed
+++ b/src/tools/clippy/tests/ui/useless_conversion.fixed
@@ -156,6 +156,20 @@ fn main() {
 }
 
 #[allow(dead_code)]
+fn issue11065_fp() {
+    use std::option::IntoIter;
+    fn takes_into_iter(_: impl IntoIterator<Item = i32>) {}
+
+    macro_rules! x {
+        ($e:expr) => {
+            takes_into_iter($e);
+            let _: IntoIter<i32> = $e; // removing `.into_iter()` leads to a type error here
+        };
+    }
+    x!(Some(5).into_iter());
+}
+
+#[allow(dead_code)]
 fn explicit_into_iter_fn_arg() {
     fn a<T>(_: T) {}
     fn b<T: IntoIterator<Item = i32>>(_: T) {}
diff --git a/src/tools/clippy/tests/ui/useless_conversion.rs b/src/tools/clippy/tests/ui/useless_conversion.rs
index 03a3e3f95ba..51ba4987339 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.rs
+++ b/src/tools/clippy/tests/ui/useless_conversion.rs
@@ -156,6 +156,20 @@ fn main() {
 }
 
 #[allow(dead_code)]
+fn issue11065_fp() {
+    use std::option::IntoIter;
+    fn takes_into_iter(_: impl IntoIterator<Item = i32>) {}
+
+    macro_rules! x {
+        ($e:expr) => {
+            takes_into_iter($e);
+            let _: IntoIter<i32> = $e; // removing `.into_iter()` leads to a type error here
+        };
+    }
+    x!(Some(5).into_iter());
+}
+
+#[allow(dead_code)]
 fn explicit_into_iter_fn_arg() {
     fn a<T>(_: T) {}
     fn b<T: IntoIterator<Item = i32>>(_: T) {}
diff --git a/src/tools/clippy/tests/ui/useless_conversion.stderr b/src/tools/clippy/tests/ui/useless_conversion.stderr
index 4957f73a469..6f7dc01d2cd 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.stderr
+++ b/src/tools/clippy/tests/ui/useless_conversion.stderr
@@ -119,61 +119,61 @@ LL |     let _ = vec![s4, s4, s4].into_iter().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![s4, s4, s4].into_iter()`
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> $DIR/useless_conversion.rs:171:7
+  --> $DIR/useless_conversion.rs:185:7
    |
 LL |     b(vec![1, 2].into_iter());
    |       ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> $DIR/useless_conversion.rs:161:13
+  --> $DIR/useless_conversion.rs:175:13
    |
 LL |     fn b<T: IntoIterator<Item = i32>>(_: T) {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> $DIR/useless_conversion.rs:172:7
+  --> $DIR/useless_conversion.rs:186:7
    |
 LL |     c(vec![1, 2].into_iter());
    |       ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> $DIR/useless_conversion.rs:162:18
+  --> $DIR/useless_conversion.rs:176:18
    |
 LL |     fn c(_: impl IntoIterator<Item = i32>) {}
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> $DIR/useless_conversion.rs:173:7
+  --> $DIR/useless_conversion.rs:187:7
    |
 LL |     d(vec![1, 2].into_iter());
    |       ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> $DIR/useless_conversion.rs:165:12
+  --> $DIR/useless_conversion.rs:179:12
    |
 LL |         T: IntoIterator<Item = i32>,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> $DIR/useless_conversion.rs:176:7
+  --> $DIR/useless_conversion.rs:190:7
    |
 LL |     b(vec![1, 2].into_iter().into_iter());
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> $DIR/useless_conversion.rs:161:13
+  --> $DIR/useless_conversion.rs:175:13
    |
 LL |     fn b<T: IntoIterator<Item = i32>>(_: T) {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> $DIR/useless_conversion.rs:177:7
+  --> $DIR/useless_conversion.rs:191:7
    |
 LL |     b(vec![1, 2].into_iter().into_iter().into_iter());
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> $DIR/useless_conversion.rs:161:13
+  --> $DIR/useless_conversion.rs:175:13
    |
 LL |     fn b<T: IntoIterator<Item = i32>>(_: T) {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 3d237eb25cc..4ef79af3124 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -18,6 +18,7 @@ use crate::ColorConfig;
 use regex::{Captures, Regex};
 use rustfix::{apply_suggestions, get_suggestions_from_json, Filter};
 
+use std::borrow::Cow;
 use std::collections::hash_map::DefaultHasher;
 use std::collections::{HashMap, HashSet};
 use std::env;
@@ -664,6 +665,7 @@ impl<'test> TestCx<'test> {
 
     fn normalize_coverage_output(&self, coverage: &str) -> Result<String, String> {
         let normalized = self.normalize_output(coverage, &[]);
+        let normalized = Self::anonymize_coverage_line_numbers(&normalized);
 
         let mut lines = normalized.lines().collect::<Vec<_>>();
 
@@ -674,6 +676,21 @@ impl<'test> TestCx<'test> {
         Ok(joined_lines)
     }
 
+    /// Replace line numbers in coverage reports with the placeholder `LL`,
+    /// so that the tests are less sensitive to lines being added/removed.
+    fn anonymize_coverage_line_numbers(coverage: &str) -> Cow<'_, str> {
+        // The coverage reporter prints line numbers at the start of a line.
+        // They are truncated or left-padded to occupy exactly 5 columns.
+        // (`LineNumberColumnWidth` in `SourceCoverageViewText.cpp`.)
+        // A pipe character `|` appears immediately after the final digit.
+        //
+        // Line numbers that appear inside expansion/instantiation subviews
+        // have an additional prefix of `  |` for each nesting level.
+        static LINE_NUMBER_RE: Lazy<Regex> =
+            Lazy::new(|| Regex::new(r"(?m:^)(?<prefix>(?:  \|)*) *[0-9]+\|").unwrap());
+        LINE_NUMBER_RE.replace_all(coverage, "$prefix   LL|")
+    }
+
     /// Coverage reports can describe multiple source files, separated by
     /// blank lines. The order of these files is unpredictable (since it
     /// depends on implementation details), so we need to sort the file
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index 90c3c70ae5b..550c9650fb3 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -971,9 +971,22 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         ecx.assert_panic(msg, unwind)
     }
 
-    #[inline(always)]
-    fn abort(_ecx: &mut MiriInterpCx<'mir, 'tcx>, msg: String) -> InterpResult<'tcx, !> {
-        throw_machine_stop!(TerminationInfo::Abort(msg))
+    fn panic_nounwind(ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &str) -> InterpResult<'tcx> {
+        ecx.start_panic_nounwind(msg)
+    }
+
+    fn unwind_terminate(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
+        // Call the lang item.
+        let panic = ecx.tcx.lang_items().panic_cannot_unwind().unwrap();
+        let panic = ty::Instance::mono(ecx.tcx.tcx, panic);
+        ecx.call_function(
+            panic,
+            Abi::Rust,
+            &[],
+            None,
+            StackPopCleanup::Goto { ret: None, unwind: mir::UnwindAction::Unreachable },
+        )?;
+        Ok(())
     }
 
     #[inline(always)]
diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs
index b2c297fe542..ea6ea5a8474 100644
--- a/src/tools/miri/src/shims/intrinsics/mod.rs
+++ b/src/tools/miri/src/shims/intrinsics/mod.rs
@@ -34,10 +34,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         if this.emulate_intrinsic(instance, args, dest, ret)? {
             return Ok(());
         }
-
-        // All remaining supported intrinsics have a return place.
         let intrinsic_name = this.tcx.item_name(instance.def_id());
         let intrinsic_name = intrinsic_name.as_str();
+
+        // Handle intrinsics without return place.
+        match intrinsic_name {
+            "abort" => {
+                throw_machine_stop!(TerminationInfo::Abort(
+                    "the program aborted execution".to_owned()
+                ))
+            }
+            _ => {},
+        }
+
+        // All remaining supported intrinsics have a return place.
         let ret = match ret {
             None => throw_unsup_format!("unimplemented (diverging) intrinsic: `{intrinsic_name}`"),
             Some(p) => p,
@@ -393,7 +403,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             "breakpoint" => {
                 let [] = check_arg_count(args)?;
                 // normally this would raise a SIGTRAP, which aborts if no debugger is connected
-                throw_machine_stop!(TerminationInfo::Abort(format!("Trace/breakpoint trap")))
+                throw_machine_stop!(TerminationInfo::Abort(format!("trace/breakpoint trap")))
             }
 
             name => throw_unsup_format!("unimplemented intrinsic: `{name}`"),
diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs
index 7aefdfcb976..5c0f828e4e6 100644
--- a/src/tools/miri/src/shims/panic.rs
+++ b/src/tools/miri/src/shims/panic.rs
@@ -188,6 +188,25 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         )
     }
 
+    /// Start a non-unwinding panic in the interpreter with the given message as payload.
+    fn start_panic_nounwind(&mut self, msg: &str) -> InterpResult<'tcx> {
+        let this = self.eval_context_mut();
+
+        // First arg: message.
+        let msg = this.allocate_str(msg, MiriMemoryKind::Machine.into(), Mutability::Not)?;
+
+        // Call the lang item.
+        let panic = this.tcx.lang_items().panic_nounwind().unwrap();
+        let panic = ty::Instance::mono(this.tcx.tcx, panic);
+        this.call_function(
+            panic,
+            Abi::Rust,
+            &[msg.to_ref(this)],
+            None,
+            StackPopCleanup::Goto { ret: None, unwind: mir::UnwindAction::Unreachable },
+        )
+    }
+
     fn assert_panic(
         &mut self,
         msg: &mir::AssertMessage<'tcx>,
diff --git a/src/tools/miri/tests/fail/breakpoint.rs b/src/tools/miri/tests/fail/breakpoint.rs
index fb1d4d958ee..2dd87ea6083 100644
--- a/src/tools/miri/tests/fail/breakpoint.rs
+++ b/src/tools/miri/tests/fail/breakpoint.rs
@@ -2,6 +2,6 @@
 
 fn main() {
     unsafe {
-        core::intrinsics::breakpoint() //~ ERROR: Trace/breakpoint trap
+        core::intrinsics::breakpoint() //~ ERROR: trace/breakpoint trap
     };
 }
diff --git a/src/tools/miri/tests/fail/breakpoint.stderr b/src/tools/miri/tests/fail/breakpoint.stderr
index 7b9bbdb3828..8b99c1493b5 100644
--- a/src/tools/miri/tests/fail/breakpoint.stderr
+++ b/src/tools/miri/tests/fail/breakpoint.stderr
@@ -1,8 +1,8 @@
-error: abnormal termination: Trace/breakpoint trap
+error: abnormal termination: trace/breakpoint trap
   --> $DIR/breakpoint.rs:LL:CC
    |
 LL |         core::intrinsics::breakpoint()
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Trace/breakpoint trap
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trace/breakpoint trap
    |
    = note: inside `main` at $DIR/breakpoint.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs
index 625a8bda8af..d47af50d407 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs
@@ -8,13 +8,13 @@ pub struct S(i32);
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 fn main() {
     mir! {
-        let unit: ();
+        let _unit: ();
         {
             let non_copy = S(42);
             let ptr = std::ptr::addr_of_mut!(non_copy);
             // Inside `callee`, the first argument and `*ptr` are basically
             // aliasing places!
-            Call(unit, after_call, callee(Move(*ptr), ptr))
+            Call(_unit = callee(Move(*ptr), ptr), after_call)
         }
         after_call = {
             Return()
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr
index 471dc1dd6dd..381442e69b1 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr
@@ -10,7 +10,7 @@ help: <TAG> was created by a SharedReadWrite retag at offsets [0x0..0x4]
   --> $DIR/arg_inplace_mutate.rs:LL:CC
    |
 LL | /     mir! {
-LL | |         let unit: ();
+LL | |         let _unit: ();
 LL | |         {
 LL | |             let non_copy = S(42);
 ...  |
@@ -27,8 +27,8 @@ LL |     unsafe { ptr.write(S(0)) };
 note: inside `main`
   --> $DIR/arg_inplace_mutate.rs:LL:CC
    |
-LL |             Call(unit, after_call, callee(Move(*ptr), ptr))
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(_unit = callee(Move(*ptr), ptr), after_call)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr
index 8393b80f25b..544cd575ada 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr
@@ -12,7 +12,7 @@ help: the accessed tag <TAG> was created here
   --> $DIR/arg_inplace_mutate.rs:LL:CC
    |
 LL | /     mir! {
-LL | |         let unit: ();
+LL | |         let _unit: ();
 LL | |         {
 LL | |             let non_copy = S(42);
 ...  |
@@ -29,8 +29,8 @@ LL |     unsafe { ptr.write(S(0)) };
 note: inside `main`
   --> $DIR/arg_inplace_mutate.rs:LL:CC
    |
-LL |             Call(unit, after_call, callee(Move(*ptr), ptr))
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(_unit = callee(Move(*ptr), ptr), after_call)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs
index 093b55759fd..ea773048dd4 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs
@@ -6,12 +6,12 @@ pub struct S(i32);
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 fn main() {
     mir! {
-        let unit: ();
+        let _unit: ();
         let _observe: i32;
         {
             let non_copy = S(42);
             // This could change `non_copy` in-place
-            Call(unit, after_call, change_arg(Move(non_copy)))
+            Call(_unit = change_arg(Move(non_copy)), after_call)
         }
         after_call = {
             // So now we must not be allowed to observe non-copy again.
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr
index baa91484793..cba23c21d12 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr
@@ -11,8 +11,8 @@ LL |     unsafe { ptr.read() };
 note: inside `main`
   --> $DIR/arg_inplace_observe_during.rs:LL:CC
    |
-LL |             Call(unit, after_call, change_arg(Move(*ptr), ptr))
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(_unit = change_arg(Move(*ptr), ptr), after_call)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs
index 2e57872db96..8c6a7df7a6d 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs
@@ -9,12 +9,12 @@ pub struct S(i32);
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 fn main() {
     mir! {
-        let unit: ();
+        let _unit: ();
         {
             let non_copy = S(42);
             let ptr = std::ptr::addr_of_mut!(non_copy);
             // This could change `non_copy` in-place
-            Call(unit, after_call, change_arg(Move(*ptr), ptr))
+            Call(_unit = change_arg(Move(*ptr), ptr), after_call)
         }
         after_call = {
             Return()
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr
index a842d3a8044..f8532186be2 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr
@@ -10,7 +10,7 @@ help: <TAG> was created by a SharedReadWrite retag at offsets [0x0..0x4]
   --> $DIR/arg_inplace_observe_during.rs:LL:CC
    |
 LL | /     mir! {
-LL | |         let unit: ();
+LL | |         let _unit: ();
 LL | |         {
 LL | |             let non_copy = S(42);
 ...  |
@@ -27,8 +27,8 @@ LL |     x.0 = 0;
 note: inside `main`
   --> $DIR/arg_inplace_observe_during.rs:LL:CC
    |
-LL |             Call(unit, after_call, change_arg(Move(*ptr), ptr))
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(_unit = change_arg(Move(*ptr), ptr), after_call)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr
index 5af4856bbe3..c33645bdd28 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr
@@ -12,7 +12,7 @@ help: the accessed tag <TAG> was created here
   --> $DIR/arg_inplace_observe_during.rs:LL:CC
    |
 LL | /     mir! {
-LL | |         let unit: ();
+LL | |         let _unit: ();
 LL | |         {
 LL | |             let non_copy = S(42);
 ...  |
@@ -29,8 +29,8 @@ LL |     x.0 = 0;
 note: inside `main`
   --> $DIR/arg_inplace_observe_during.rs:LL:CC
    |
-LL |             Call(unit, after_call, change_arg(Move(*ptr), ptr))
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(_unit = change_arg(Move(*ptr), ptr), after_call)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
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 bf5199307f6..e4821bc0bac 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,22 +1,35 @@
 thread 'main' panicked at $DIR/exported_symbol_bad_unwind2.rs:LL:CC:
 explicit panic
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-error: abnormal termination: panic in a function that cannot unwind
+thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
+panic in a function that cannot unwind
+stack backtrace:
+thread caused non-unwinding panic. aborting.
+error: abnormal termination: the program aborted execution
+  --> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   |
+LL |     ABORT();
+   | ^ the program aborted execution
+   |
+   = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
+   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+note: inside `nounwind`
   --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
    |
 LL | / extern "C-unwind" fn nounwind() {
-LL | |
-LL | |
 LL | |     panic!();
 LL | | }
-   | |_^ panic in a function that cannot unwind
-   |
-   = note: inside `nounwind` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
+   | |_^
 note: inside `main`
   --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
    |
 LL |     unsafe { nounwind() }
-   |              ^^^^^^^^^^
+   | ^
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
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 bf5199307f6..e4821bc0bac 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,22 +1,35 @@
 thread 'main' panicked at $DIR/exported_symbol_bad_unwind2.rs:LL:CC:
 explicit panic
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-error: abnormal termination: panic in a function that cannot unwind
+thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
+panic in a function that cannot unwind
+stack backtrace:
+thread caused non-unwinding panic. aborting.
+error: abnormal termination: the program aborted execution
+  --> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   |
+LL |     ABORT();
+   | ^ the program aborted execution
+   |
+   = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
+   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+note: inside `nounwind`
   --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
    |
 LL | / extern "C-unwind" fn nounwind() {
-LL | |
-LL | |
 LL | |     panic!();
 LL | | }
-   | |_^ panic in a function that cannot unwind
-   |
-   = note: inside `nounwind` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
+   | |_^
 note: inside `main`
   --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
    |
 LL |     unsafe { nounwind() }
-   |              ^^^^^^^^^^
+   | ^
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr
index c774bd4dd91..25e13d74754 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr
@@ -5,7 +5,7 @@ error: Undefined Behavior: unwinding past a stack frame that does not allow unwi
   --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
    |
 LL |     unsafe { nounwind() }
-   |              ^^^^^^^^^^ unwinding past a stack frame that does not allow unwinding
+   | ^ unwinding past a stack frame that does not allow unwinding
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs
index 65ba3433c28..10bd5eb7211 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
@@ -1,11 +1,14 @@
 //@revisions: extern_block definition both
+//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\| +\^+" -> "| ^"
+//@normalize-stderr-test: "\n  +[0-9]+:[^\n]+" -> "$1"
+//@normalize-stderr-test: "\n at [^\n]+" -> "$1"
+//@[definition,both]error-in-other-file: aborted execution
 #![feature(rustc_attrs, c_unwind)]
 
 #[cfg_attr(any(definition, both), rustc_nounwind)]
 #[no_mangle]
 extern "C-unwind" fn nounwind() {
-    //~[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/function_calls/return_pointer_aliasing.none.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr
index 9d9dfc89f89..0a31adabf73 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr
@@ -11,8 +11,8 @@ LL |     unsafe { ptr.read() };
 note: inside `main`
   --> $DIR/return_pointer_aliasing.rs:LL:CC
    |
-LL |             Call(*ptr, after_call, myfun(ptr))
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(*ptr = myfun(ptr), after_call)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs
index 829809102fa..3d560af3d5e 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs
@@ -15,7 +15,7 @@ pub fn main() {
             let ptr = &raw mut x;
             // We arrange for `myfun` to have a pointer that aliases
             // its return place. Even just reading from that pointer is UB.
-            Call(*ptr, after_call, myfun(ptr))
+            Call(*ptr = myfun(ptr), after_call)
         }
 
         after_call = {
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr
index d486dcb95df..875cc5edad9 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr
@@ -27,8 +27,8 @@ LL |     unsafe { ptr.read() };
 note: inside `main`
   --> $DIR/return_pointer_aliasing.rs:LL:CC
    |
-LL |             Call(*ptr, after_call, myfun(ptr))
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(*ptr = myfun(ptr), after_call)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr
index c491a904a10..66c2fb8db19 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr
@@ -29,8 +29,8 @@ LL |     unsafe { ptr.read() };
 note: inside `main`
   --> $DIR/return_pointer_aliasing.rs:LL:CC
    |
-LL |             Call(*ptr, after_call, myfun(ptr))
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(*ptr = myfun(ptr), after_call)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs
index 7e9a6320026..9d53faccd1e 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs
@@ -9,11 +9,11 @@ use std::intrinsics::mir::*;
 pub fn main() {
     mir! {
         {
-            let x = 0;
-            let ptr = &raw mut x;
+            let _x = 0;
+            let ptr = &raw mut _x;
             // We arrange for `myfun` to have a pointer that aliases
             // its return place. Even just reading from that pointer is UB.
-            Call(x, after_call, myfun(ptr))
+            Call(_x = myfun(ptr), after_call)
         }
 
         after_call = {
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stderr
index 33a8a4b46bd..443ee8643fc 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stderr
@@ -13,8 +13,8 @@ help: the accessed tag <TAG> was created here
    |
 LL | /     mir! {
 LL | |         {
-LL | |             let x = 0;
-LL | |             let ptr = &raw mut x;
+LL | |             let _x = 0;
+LL | |             let ptr = &raw mut _x;
 ...  |
 LL | |         }
 LL | |     }
@@ -29,8 +29,8 @@ LL |     unsafe { ptr.write(0) };
 note: inside `main`
   --> $DIR/return_pointer_aliasing2.rs:LL:CC
    |
-LL |             Call(x, after_call, myfun(ptr))
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(_x = myfun(ptr), after_call)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs
index 59781f02366..b8fa32c986f 100644
--- a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs
+++ b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs
@@ -1,7 +1,11 @@
+//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\| +\^+" -> "| ^"
+//@normalize-stderr-test: "\n  +[0-9]+:[^\n]+" -> "$1"
+//@normalize-stderr-test: "\n at [^\n]+" -> "$1"
+//@error-in-other-file: aborted execution
 #![feature(never_type)]
 
 #[allow(deprecated, invalid_value)]
 fn main() {
     let _ = unsafe { std::mem::uninitialized::<!>() };
-    //~^ ERROR: attempted to instantiate uninhabited type `!`
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr
index f2cc3430326..70e10e8dc48 100644
--- a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr
@@ -1,10 +1,24 @@
-error: abnormal termination: aborted execution: attempted to instantiate uninhabited type `!`
+thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
+aborted execution: attempted to instantiate uninhabited type `!`
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+thread caused non-unwinding panic. aborting.
+error: abnormal termination: the program aborted execution
+  --> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   |
+LL |     ABORT();
+   | ^ the program aborted execution
+   |
+   = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
+   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+note: inside `main`
   --> $DIR/uninit_uninhabited_type.rs:LL:CC
    |
 LL |     let _ = unsafe { std::mem::uninitialized::<!>() };
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!`
-   |
-   = note: inside `main` at $DIR/uninit_uninhabited_type.rs:LL:CC
+   | ^
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs
index e9c6e464e88..70ae60593a1 100644
--- a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs
+++ b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs
@@ -1,5 +1,10 @@
+//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\| +\^+" -> "| ^"
+//@normalize-stderr-test: "\n  +[0-9]+:[^\n]+" -> "$1"
+//@normalize-stderr-test: "\n at [^\n]+" -> "$1"
+//@error-in-other-file: aborted execution
+
 #[allow(deprecated, invalid_value)]
 fn main() {
     let _ = unsafe { std::mem::zeroed::<fn()>() };
-    //~^ ERROR: attempted to zero-initialize type `fn()`, which is invalid
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr
index 77d58228043..56143b6c205 100644
--- a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr
@@ -1,10 +1,24 @@
-error: abnormal termination: aborted execution: attempted to zero-initialize type `fn()`, which is invalid
+thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
+aborted execution: attempted to zero-initialize type `fn()`, which is invalid
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+thread caused non-unwinding panic. aborting.
+error: abnormal termination: the program aborted execution
+  --> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   |
+LL |     ABORT();
+   | ^ the program aborted execution
+   |
+   = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
+   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+note: inside `main`
   --> $DIR/zero_fn_ptr.rs:LL:CC
    |
 LL |     let _ = unsafe { std::mem::zeroed::<fn()>() };
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `fn()`, which is invalid
-   |
-   = note: inside `main` at $DIR/zero_fn_ptr.rs:LL:CC
+   | ^
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/panic/double_panic.rs b/src/tools/miri/tests/fail/panic/double_panic.rs
index adb30714269..4627e9f1c8e 100644
--- a/src/tools/miri/tests/fail/panic/double_panic.rs
+++ b/src/tools/miri/tests/fail/panic/double_panic.rs
@@ -1,6 +1,8 @@
+//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
 //@normalize-stderr-test: "\n  +[0-9]+:[^\n]+" -> "$1"
 //@normalize-stderr-test: "\n at [^\n]+" -> "$1"
+//@error-in-other-file: aborted execution
 
 struct Foo;
 impl Drop for Foo {
@@ -9,7 +11,6 @@ impl Drop for Foo {
     }
 }
 fn main() {
-    //~^ERROR: panic in a function that cannot unwind
     let _foo = Foo;
     panic!("first");
 }
diff --git a/src/tools/miri/tests/fail/panic/double_panic.stderr b/src/tools/miri/tests/fail/panic/double_panic.stderr
index 8e008da75ee..25c9a7c44bc 100644
--- a/src/tools/miri/tests/fail/panic/double_panic.stderr
+++ b/src/tools/miri/tests/fail/panic/double_panic.stderr
@@ -4,17 +4,31 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 thread 'main' panicked at $DIR/double_panic.rs:LL:CC:
 second
 stack backtrace:
-error: abnormal termination: panic in a function that cannot unwind
+thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
+panic in a function that cannot unwind
+stack backtrace:
+thread caused non-unwinding panic. aborting.
+error: abnormal termination: the program aborted execution
+  --> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   |
+LL |     ABORT();
+   | ^ the program aborted execution
+   |
+   = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
+   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+note: inside `main`
   --> $DIR/double_panic.rs:LL:CC
    |
 LL | / fn main() {
-LL | |
 LL | |     let _foo = Foo;
 LL | |     panic!("first");
 LL | | }
-   | |_^ panic in a function that cannot unwind
-   |
-   = note: inside `main` at $DIR/double_panic.rs:LL:CC
+   | |_^
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/terminate-terminator.rs b/src/tools/miri/tests/fail/terminate-terminator.rs
index bd6cd69215a..5373b5f70c0 100644
--- a/src/tools/miri/tests/fail/terminate-terminator.rs
+++ b/src/tools/miri/tests/fail/terminate-terminator.rs
@@ -1,5 +1,10 @@
 //@compile-flags: -Zmir-opt-level=3 -Zinline-mir-hint-threshold=1000
-// Enable MIR inlining to ensure that `TerminatorKind::Terminate` is generated
+//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\| +\^+" -> "| ^"
+//@normalize-stderr-test: "\n  +[0-9]+:[^\n]+" -> "$1"
+//@normalize-stderr-test: "\n at [^\n]+" -> "$1"
+//@error-in-other-file: aborted execution
+// Enable MIR inlining to ensure that `TerminatorKind::UnwindTerminate` is generated
 // instead of just `UnwindAction::Terminate`.
 
 #![feature(c_unwind)]
@@ -12,7 +17,6 @@ impl Drop for Foo {
 
 #[inline(always)]
 fn has_cleanup() {
-    //~^ ERROR: panic in a function that cannot unwind
     let _f = Foo;
     panic!();
 }
diff --git a/src/tools/miri/tests/fail/terminate-terminator.stderr b/src/tools/miri/tests/fail/terminate-terminator.stderr
index 4f73b599a3f..e9277ebdbfd 100644
--- a/src/tools/miri/tests/fail/terminate-terminator.stderr
+++ b/src/tools/miri/tests/fail/terminate-terminator.stderr
@@ -3,27 +3,41 @@ warning: You have explicitly enabled MIR optimizations, overriding Miri's defaul
 thread 'main' panicked at $DIR/terminate-terminator.rs:LL:CC:
 explicit panic
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-error: abnormal termination: panic in a function that cannot unwind
+thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
+panic in a function that cannot unwind
+stack backtrace:
+thread caused non-unwinding panic. aborting.
+error: abnormal termination: the program aborted execution
+  --> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   |
+LL |     ABORT();
+   | ^ the program aborted execution
+   |
+   = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
+   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+note: inside `has_cleanup`
   --> $DIR/terminate-terminator.rs:LL:CC
    |
 LL | / fn has_cleanup() {
-LL | |
 LL | |     let _f = Foo;
 LL | |     panic!();
 LL | | }
-   | |_^ panic in a function that cannot unwind
-   |
-   = note: inside `has_cleanup` at $DIR/terminate-terminator.rs:LL:CC
+   | |_^
 note: inside `panic_abort`
   --> $DIR/terminate-terminator.rs:LL:CC
    |
 LL |     has_cleanup();
-   |     ^^^^^^^^^^^^^
+   | ^
 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
 
diff --git a/src/tools/miri/tests/fail/unwind-action-terminate.rs b/src/tools/miri/tests/fail/unwind-action-terminate.rs
index 876b9a9ab0a..77844844483 100644
--- a/src/tools/miri/tests/fail/unwind-action-terminate.rs
+++ b/src/tools/miri/tests/fail/unwind-action-terminate.rs
@@ -1,7 +1,11 @@
+//@error-in-other-file: aborted execution
+//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\| +\^+" -> "| ^"
+//@normalize-stderr-test: "\n  +[0-9]+:[^\n]+" -> "$1"
+//@normalize-stderr-test: "\n at [^\n]+" -> "$1"
 #![feature(c_unwind)]
 
 extern "C" fn panic_abort() {
-    //~^ ERROR: panic in a function that cannot unwind
     panic!()
 }
 
diff --git a/src/tools/miri/tests/fail/unwind-action-terminate.stderr b/src/tools/miri/tests/fail/unwind-action-terminate.stderr
index daa4a808df9..cf94dbb9909 100644
--- a/src/tools/miri/tests/fail/unwind-action-terminate.stderr
+++ b/src/tools/miri/tests/fail/unwind-action-terminate.stderr
@@ -1,21 +1,35 @@
 thread 'main' panicked at $DIR/unwind-action-terminate.rs:LL:CC:
 explicit panic
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-error: abnormal termination: panic in a function that cannot unwind
+thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
+panic in a function that cannot unwind
+stack backtrace:
+thread caused non-unwinding panic. aborting.
+error: abnormal termination: the program aborted execution
+  --> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   |
+LL |     ABORT();
+   | ^ the program aborted execution
+   |
+   = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
+   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+note: inside `panic_abort`
   --> $DIR/unwind-action-terminate.rs:LL:CC
    |
 LL | / extern "C" fn panic_abort() {
-LL | |
 LL | |     panic!()
 LL | | }
-   | |_^ panic in a function that cannot unwind
-   |
-   = note: inside `panic_abort` at $DIR/unwind-action-terminate.rs:LL:CC
+   | |_^
 note: inside `main`
   --> $DIR/unwind-action-terminate.rs:LL:CC
    |
 LL |     panic_abort();
-   |     ^^^^^^^^^^^^^
+   | ^
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs b/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs
index dcfebd0f82b..d410a875b1b 100644
--- a/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs
+++ b/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs
@@ -11,7 +11,7 @@ pub fn main() {
         {
             let x = 0;
             let ptr = &raw mut x;
-            Call(*ptr, after_call, myfun())
+            Call(*ptr = myfun(), after_call)
         }
 
         after_call = {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
index 4723c25ed08..9be083d0117 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
@@ -368,7 +368,7 @@ pub enum TerminatorKind {
     ///
     /// Only permitted in cleanup blocks. `Resume` is not permitted with `-C unwind=abort` after
     /// deaggregation runs.
-    Resume,
+    UnwindResume,
 
     /// Indicates that the landing pad is finished and that the process should abort.
     ///
@@ -1057,7 +1057,7 @@ impl MirBody {
                     TerminatorKind::FalseEdge { .. }
                     | TerminatorKind::FalseUnwind { .. }
                     | TerminatorKind::Goto { .. }
-                    | TerminatorKind::Resume
+                    | TerminatorKind::UnwindResume
                     | TerminatorKind::GeneratorDrop
                     | TerminatorKind::Abort
                     | TerminatorKind::Return
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs
index ad98e8fa181..c70d7f63fd8 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs
@@ -160,7 +160,7 @@ fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec<MovedOutOfRef>
                 TerminatorKind::FalseEdge { .. }
                 | TerminatorKind::FalseUnwind { .. }
                 | TerminatorKind::Goto { .. }
-                | TerminatorKind::Resume
+                | TerminatorKind::UnwindResume
                 | TerminatorKind::GeneratorDrop
                 | TerminatorKind::Abort
                 | TerminatorKind::Return
@@ -280,7 +280,7 @@ fn ever_initialized_map(
         let targets = match &terminator.kind {
             TerminatorKind::Goto { target } => vec![*target],
             TerminatorKind::SwitchInt { targets, .. } => targets.all_targets().to_vec(),
-            TerminatorKind::Resume
+            TerminatorKind::UnwindResume
             | TerminatorKind::Abort
             | TerminatorKind::Return
             | TerminatorKind::Unreachable => vec![],
@@ -371,7 +371,7 @@ fn mutability_of_locals(
         };
         match &terminator.kind {
             TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
+            | TerminatorKind::UnwindResume
             | TerminatorKind::Abort
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs
index c565228d91e..df16d0d8201 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs
@@ -265,7 +265,7 @@ impl Filler<'_> {
                         self.fill_operand(discr)?;
                     }
                     TerminatorKind::Goto { .. }
-                    | TerminatorKind::Resume
+                    | TerminatorKind::UnwindResume
                     | TerminatorKind::Abort
                     | TerminatorKind::Return
                     | TerminatorKind::Unreachable
diff --git a/src/version b/src/version
index 5e3a4256626..dc87e8af82f 100644
--- a/src/version
+++ b/src/version
@@ -1 +1 @@
-1.73.0
+1.74.0
diff --git a/tests/codegen/issues/issue-114312.rs b/tests/codegen/issues/issue-114312.rs
new file mode 100644
index 00000000000..e2fbcef721e
--- /dev/null
+++ b/tests/codegen/issues/issue-114312.rs
@@ -0,0 +1,27 @@
+// compile-flags: -O
+// min-llvm-version: 17
+// only-x86_64-unknown-linux-gnu
+
+// We want to check that this function does not mis-optimize to loop jumping.
+
+#![crate_type = "lib"]
+
+#[repr(C)]
+pub enum Expr {
+    Sum,
+    // must have more than usize data
+    Sub(usize, u8),
+}
+
+#[no_mangle]
+pub extern "C" fn issue_114312(expr: Expr) {
+    // CHECK-LABEL: @issue_114312(
+    // CHECK-NOT: readonly
+    // CHECK-SAME: byval
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: ret void
+    match expr {
+        Expr::Sum => {}
+        Expr::Sub(_, _) => issue_114312(Expr::Sum),
+    }
+}
diff --git a/tests/codegen/slice-ref-equality.rs b/tests/codegen/slice-ref-equality.rs
index 4d0dce7b074..afbdf66ce0a 100644
--- a/tests/codegen/slice-ref-equality.rs
+++ b/tests/codegen/slice-ref-equality.rs
@@ -44,48 +44,48 @@ pub fn is_zero_array(data: &[u8; 4]) -> bool {
 // equality for non-byte types also just emit a `bcmp`, not a loop.
 
 // CHECK-LABEL: @eq_slice_of_nested_u8(
-// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1
-// CHECK-SAME: [[USIZE]] noundef %y.1
+// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
+// CHECK-SAME: [[USIZE]] noundef %3
 #[no_mangle]
 fn eq_slice_of_nested_u8(x: &[[u8; 3]], y: &[[u8; 3]]) -> bool {
-    // CHECK: icmp eq [[USIZE]] %x.1, %y.1
-    // CHECK: %[[BYTES:.+]] = mul nsw [[USIZE]] %x.1, 3
+    // CHECK: icmp eq [[USIZE]] %1, %3
+    // CHECK: %[[BYTES:.+]] = mul nsw [[USIZE]] %1, 3
     // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}(ptr
     // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
     x == y
 }
 
 // CHECK-LABEL: @eq_slice_of_i32(
-// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1
-// CHECK-SAME: [[USIZE]] noundef %y.1
+// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
+// CHECK-SAME: [[USIZE]] noundef %3
 #[no_mangle]
 fn eq_slice_of_i32(x: &[i32], y: &[i32]) -> bool {
-    // CHECK: icmp eq [[USIZE]] %x.1, %y.1
-    // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 2
+    // CHECK: icmp eq [[USIZE]] %1, %3
+    // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 2
     // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}(ptr
     // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
     x == y
 }
 
 // CHECK-LABEL: @eq_slice_of_nonzero(
-// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1
-// CHECK-SAME: [[USIZE]] noundef %y.1
+// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
+// CHECK-SAME: [[USIZE]] noundef %3
 #[no_mangle]
 fn eq_slice_of_nonzero(x: &[NonZeroU32], y: &[NonZeroU32]) -> bool {
-    // CHECK: icmp eq [[USIZE]] %x.1, %y.1
-    // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 2
+    // CHECK: icmp eq [[USIZE]] %1, %3
+    // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 2
     // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}(ptr
     // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
     x == y
 }
 
 // CHECK-LABEL: @eq_slice_of_option_of_nonzero(
-// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1
-// CHECK-SAME: [[USIZE]] noundef %y.1
+// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
+// CHECK-SAME: [[USIZE]] noundef %3
 #[no_mangle]
 fn eq_slice_of_option_of_nonzero(x: &[Option<NonZeroI16>], y: &[Option<NonZeroI16>]) -> bool {
-    // CHECK: icmp eq [[USIZE]] %x.1, %y.1
-    // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 1
+    // CHECK: icmp eq [[USIZE]] %1, %3
+    // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 1
     // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}(ptr
     // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
     x == y
diff --git a/tests/codegen/trailing_zeros.rs b/tests/codegen/trailing_zeros.rs
new file mode 100644
index 00000000000..2ea0e447abe
--- /dev/null
+++ b/tests/codegen/trailing_zeros.rs
@@ -0,0 +1,22 @@
+// compile-flags: -O
+// min-llvm-version: 17
+
+#![crate_type = "lib"]
+
+// CHECK-LABEL: @trailing_zeros_ge
+#[no_mangle]
+pub fn trailing_zeros_ge(val: u32) -> bool {
+    // CHECK: %[[AND:.*]] = and i32 %val, 7
+    // CHECK: %[[ICMP:.*]] = icmp eq i32 %[[AND]], 0
+    // CHECK: ret i1 %[[ICMP]]
+    val.trailing_zeros() >= 3
+}
+
+// CHECK-LABEL: @trailing_zeros_gt
+#[no_mangle]
+pub fn trailing_zeros_gt(val: u64) -> bool {
+    // CHECK: %[[AND:.*]] = and i64 %val, 15
+    // CHECK: %[[ICMP:.*]] = icmp eq i64 %[[AND]], 0
+    // CHECK: ret i1 %[[ICMP]]
+    val.trailing_zeros() > 3
+}
diff --git a/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff b/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff
index 9c7b3c5197b..15269fb8f6c 100644
--- a/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff
+++ b/tests/mir-opt/basic_assignment.main.ElaborateDrops.diff
@@ -47,7 +47,8 @@
   
       bb2 (cleanup): {
           _5 = move _6;
-          drop(_6) -> [return: bb6, unwind terminate];
+-         drop(_6) -> [return: bb6, unwind terminate];
++         goto -> bb6;
       }
   
       bb3: {
@@ -70,7 +71,8 @@
       }
   
       bb6 (cleanup): {
-          drop(_5) -> [return: bb7, unwind terminate];
+-         drop(_5) -> [return: bb7, unwind terminate];
++         goto -> bb7;
       }
   
       bb7 (cleanup): {
@@ -80,10 +82,6 @@
   
       bb8 (cleanup): {
           resume;
-+     }
-+ 
-+     bb9 (cleanup): {
-+         unreachable;
       }
   }
   
diff --git a/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir b/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir
index 074ebddf78b..9be5b8509c7 100644
--- a/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir
+++ b/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir
@@ -30,7 +30,7 @@ fn a::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:11:14: 11:16]>
     }
 
     bb2: {
-        assert(const false, "`async fn` resumed after completion") -> [success: bb2, unwind continue];
+        assert(const false, "`async fn` resumed after completion") -> [success: bb2, unwind unreachable];
     }
 
     bb3: {
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 f774f32eb23..80ac92d59f3 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
@@ -310,7 +310,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>,
     }
 
     bb28: {
-        assert(const false, "`async fn` resumed after completion") -> [success: bb28, unwind continue];
+        assert(const false, "`async fn` resumed after completion") -> [success: bb28, unwind unreachable];
     }
 
     bb29: {
diff --git a/tests/mir-opt/building/custom/terminators.rs b/tests/mir-opt/building/custom/terminators.rs
index f1240566168..123118f654e 100644
--- a/tests/mir-opt/building/custom/terminators.rs
+++ b/tests/mir-opt/building/custom/terminators.rs
@@ -12,7 +12,7 @@ fn ident<T>(t: T) -> T {
 fn direct_call(x: i32) -> i32 {
     mir!(
         {
-            Call(RET, retblock, ident(x))
+            Call(RET = ident(x), retblock)
         }
 
         retblock = {
@@ -26,7 +26,7 @@ fn direct_call(x: i32) -> i32 {
 fn indirect_call(x: i32, f: fn(i32) -> i32) -> i32 {
     mir!(
         {
-            Call(RET, retblock, f(x))
+            Call(RET = f(x), retblock)
         }
 
         retblock = {
diff --git a/tests/mir-opt/copy-prop/borrowed_local.rs b/tests/mir-opt/copy-prop/borrowed_local.rs
index a89b64441d0..bf94dc57d33 100644
--- a/tests/mir-opt/copy-prop/borrowed_local.rs
+++ b/tests/mir-opt/copy-prop/borrowed_local.rs
@@ -21,11 +21,11 @@ fn f() -> bool {
             let b = a;
             // We cannot propagate the place `a`.
             let r2 = &b;
-            Call(RET, next, cmp_ref(r1, r2))
+            Call(RET = cmp_ref(r1, r2), next)
         }
         next = {
             // But we can propagate the value `a`.
-            Call(RET, ret, opaque(b))
+            Call(RET = opaque(b), ret)
         }
         ret = {
             Return()
diff --git a/tests/mir-opt/copy-prop/custom_move_arg.rs b/tests/mir-opt/copy-prop/custom_move_arg.rs
index a90db08fa51..d1c5ffdff0d 100644
--- a/tests/mir-opt/copy-prop/custom_move_arg.rs
+++ b/tests/mir-opt/copy-prop/custom_move_arg.rs
@@ -13,11 +13,11 @@ struct NotCopy(bool);
 fn f(_1: NotCopy) {
     mir!({
         let _2 = _1;
-        Call(RET, bb1, opaque(Move(_1)))
+        Call(RET = opaque(Move(_1)), bb1)
     }
     bb1 = {
         let _3 = Move(_2);
-        Call(RET, bb2, opaque(_3))
+        Call(RET = opaque(_3), bb2)
     }
     bb2 = {
         Return()
diff --git a/tests/mir-opt/copy-prop/move_projection.rs b/tests/mir-opt/copy-prop/move_projection.rs
index 40f51ce8406..f94addb5629 100644
--- a/tests/mir-opt/copy-prop/move_projection.rs
+++ b/tests/mir-opt/copy-prop/move_projection.rs
@@ -17,10 +17,10 @@ fn f(a: Foo) -> bool {
             let b = a;
             // This is a move out of a copy, so must become a copy of `a.0`.
             let c = Move(b.0);
-            Call(RET, bb1, opaque(Move(a)))
+            Call(RET = opaque(Move(a)), bb1)
         }
         bb1 = {
-            Call(RET, ret, opaque(Move(c)))
+            Call(RET = opaque(Move(c)), ret)
         }
         ret = {
             Return()
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff
index 486f276b21c..e3c57347392 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff
@@ -7,7 +7,8 @@
       let mut _2: std::option::Option<T>;
 +     scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
 +         debug self => _2;
-+         let mut _3: isize;
++         let mut _3: &std::option::Option<T>;
++         let mut _4: isize;
 +         scope 2 {
 +             debug val => _0;
 +         }
@@ -20,7 +21,7 @@
 +             }
 +         }
 +         scope 4 (inlined Option::<T>::is_some) {
-+             debug self => &_2;
++             debug self => _3;
 +         }
 +     }
   
@@ -28,8 +29,9 @@
           StorageLive(_2);
           _2 = move _1;
 -         _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind unreachable];
-+         _3 = discriminant(_2);
-+         switchInt(move _3) -> [1: bb2, otherwise: bb1];
++         StorageLive(_3);
++         _4 = discriminant(_2);
++         switchInt(move _4) -> [1: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -38,6 +40,7 @@
 + 
 +     bb2: {
 +         _0 = move ((_2 as Some).0: T);
++         StorageDead(_3);
           StorageDead(_2);
           return;
       }
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff
index 1c3aa537946..fc638cb3ace 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff
@@ -7,7 +7,8 @@
       let mut _2: std::option::Option<T>;
 +     scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
 +         debug self => _2;
-+         let mut _3: isize;
++         let mut _3: &std::option::Option<T>;
++         let mut _4: isize;
 +         scope 2 {
 +             debug val => _0;
 +         }
@@ -20,7 +21,7 @@
 +             }
 +         }
 +         scope 4 (inlined Option::<T>::is_some) {
-+             debug self => &_2;
++             debug self => _3;
 +         }
 +     }
   
@@ -28,8 +29,9 @@
           StorageLive(_2);
           _2 = move _1;
 -         _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind: bb2];
-+         _3 = discriminant(_2);
-+         switchInt(move _3) -> [1: bb2, otherwise: bb1];
++         StorageLive(_3);
++         _4 = discriminant(_2);
++         switchInt(move _4) -> [1: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -42,6 +44,7 @@
 -         resume;
 +     bb2: {
 +         _0 = move ((_2 as Some).0: T);
++         StorageDead(_3);
 +         StorageDead(_2);
 +         return;
       }
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir
index 82238626798..fcc4d43ced6 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir
@@ -6,6 +6,7 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
     scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
         debug self => _1;
         let mut _2: isize;
+        let mut _3: &std::option::Option<T>;
         scope 2 {
             debug val => _0;
         }
@@ -18,17 +19,19 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
             }
         }
         scope 4 (inlined Option::<T>::is_some) {
-            debug self => &_1;
+            debug self => _3;
         }
     }
 
     bb0: {
+        StorageLive(_3);
         _2 = discriminant(_1);
         switchInt(move _2) -> [1: bb1, otherwise: bb2];
     }
 
     bb1: {
         _0 = move ((_1 as Some).0: T);
+        StorageDead(_3);
         return;
     }
 
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir
index 82238626798..fcc4d43ced6 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir
@@ -6,6 +6,7 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
     scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
         debug self => _1;
         let mut _2: isize;
+        let mut _3: &std::option::Option<T>;
         scope 2 {
             debug val => _0;
         }
@@ -18,17 +19,19 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
             }
         }
         scope 4 (inlined Option::<T>::is_some) {
-            debug self => &_1;
+            debug self => _3;
         }
     }
 
     bb0: {
+        StorageLive(_3);
         _2 = discriminant(_1);
         switchInt(move _2) -> [1: bb1, otherwise: bb2];
     }
 
     bb1: {
         _0 = move ((_1 as Some).0: T);
+        StorageDead(_3);
         return;
     }
 
diff --git a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-abort.diff b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-abort.diff
index eb03a347a19..65f4806aaf7 100644
--- a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-abort.diff
+++ b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-abort.diff
@@ -47,7 +47,8 @@
   
       bb3 (cleanup): {
           _2 = move _5;
-          drop(_5) -> [return: bb8, unwind terminate];
+-         drop(_5) -> [return: bb8, unwind terminate];
++         goto -> bb8;
       }
   
       bb4: {
@@ -80,7 +81,7 @@
   
       bb9 (cleanup): {
 -         drop(_1) -> [return: bb10, unwind terminate];
-+         goto -> bb13;
++         goto -> bb12;
       }
   
       bb10 (cleanup): {
@@ -88,15 +89,11 @@
 +     }
 + 
 +     bb11 (cleanup): {
-+         unreachable;
-+     }
-+ 
-+     bb12 (cleanup): {
 +         drop(_1) -> [return: bb10, unwind terminate];
 +     }
 + 
-+     bb13 (cleanup): {
-+         switchInt(_6) -> [0: bb10, otherwise: bb12];
++     bb12 (cleanup): {
++         switchInt(_6) -> [0: bb10, otherwise: bb11];
       }
   }
   
diff --git a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff
index 254658c810d..4845fc732aa 100644
--- a/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff
+++ b/tests/mir-opt/issue_41110.test.ElaborateDrops.panic-unwind.diff
@@ -47,7 +47,8 @@
   
       bb3 (cleanup): {
           _2 = move _5;
-          drop(_5) -> [return: bb8, unwind terminate];
+-         drop(_5) -> [return: bb8, unwind terminate];
++         goto -> bb8;
       }
   
       bb4: {
@@ -80,7 +81,7 @@
   
       bb9 (cleanup): {
 -         drop(_1) -> [return: bb10, unwind terminate];
-+         goto -> bb13;
++         goto -> bb12;
       }
   
       bb10 (cleanup): {
@@ -88,15 +89,11 @@
 +     }
 + 
 +     bb11 (cleanup): {
-+         unreachable;
-+     }
-+ 
-+     bb12 (cleanup): {
 +         drop(_1) -> [return: bb10, unwind terminate];
 +     }
 + 
-+     bb13 (cleanup): {
-+         switchInt(_6) -> [0: bb10, otherwise: bb12];
++     bb12 (cleanup): {
++         switchInt(_6) -> [0: bb10, otherwise: bb11];
       }
   }
   
diff --git a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-abort.diff b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-abort.diff
index 7c2503f9d3e..aca7fe95c18 100644
--- a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-abort.diff
+++ b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-abort.diff
@@ -54,8 +54,12 @@
       }
   
       bb4 (cleanup): {
++         _7 = const true;
++         _8 = const true;
++         _9 = const true;
           _1 = move _3;
-          drop(_3) -> [return: bb11, unwind terminate];
+-         drop(_3) -> [return: bb11, unwind terminate];
++         goto -> bb11;
       }
   
       bb5: {
@@ -86,7 +90,7 @@
       bb9: {
           StorageDead(_2);
 -         drop(_1) -> [return: bb10, unwind: bb12];
-+         goto -> bb19;
++         goto -> bb18;
       }
   
       bb10: {
@@ -106,43 +110,39 @@
           resume;
 +     }
 + 
-+     bb13 (cleanup): {
-+         unreachable;
-+     }
-+ 
-+     bb14: {
++     bb13: {
 +         _7 = const false;
 +         goto -> bb10;
 +     }
 + 
-+     bb15 (cleanup): {
++     bb14 (cleanup): {
 +         goto -> bb12;
 +     }
 + 
-+     bb16: {
-+         drop(_1) -> [return: bb14, unwind: bb12];
++     bb15: {
++         drop(_1) -> [return: bb13, unwind: bb12];
 +     }
 + 
-+     bb17 (cleanup): {
++     bb16 (cleanup): {
 +         drop(_1) -> [return: bb12, unwind terminate];
 +     }
 + 
-+     bb18: {
++     bb17: {
 +         _10 = discriminant(_1);
-+         switchInt(move _10) -> [0: bb14, otherwise: bb16];
++         switchInt(move _10) -> [0: bb13, otherwise: bb15];
 +     }
 + 
-+     bb19: {
-+         switchInt(_7) -> [0: bb14, otherwise: bb18];
++     bb18: {
++         switchInt(_7) -> [0: bb13, otherwise: bb17];
 +     }
 + 
-+     bb20 (cleanup): {
++     bb19 (cleanup): {
 +         _11 = discriminant(_1);
-+         switchInt(move _11) -> [0: bb15, otherwise: bb17];
++         switchInt(move _11) -> [0: bb14, otherwise: bb16];
 +     }
 + 
-+     bb21 (cleanup): {
-+         switchInt(_7) -> [0: bb12, otherwise: bb20];
++     bb20 (cleanup): {
++         switchInt(_7) -> [0: bb12, otherwise: bb19];
       }
   }
   
diff --git a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff
index 4ef3650cdea..60ce9cd8ad9 100644
--- a/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff
+++ b/tests/mir-opt/issue_41888.main.ElaborateDrops.panic-unwind.diff
@@ -54,8 +54,12 @@
       }
   
       bb4 (cleanup): {
++         _7 = const true;
++         _8 = const true;
++         _9 = const true;
           _1 = move _3;
-          drop(_3) -> [return: bb11, unwind terminate];
+-         drop(_3) -> [return: bb11, unwind terminate];
++         goto -> bb11;
       }
   
       bb5: {
@@ -86,7 +90,7 @@
       bb9: {
           StorageDead(_2);
 -         drop(_1) -> [return: bb10, unwind continue];
-+         goto -> bb19;
++         goto -> bb18;
       }
   
       bb10: {
@@ -106,43 +110,39 @@
           resume;
 +     }
 + 
-+     bb13 (cleanup): {
-+         unreachable;
-+     }
-+ 
-+     bb14: {
++     bb13: {
 +         _7 = const false;
 +         goto -> bb10;
 +     }
 + 
-+     bb15 (cleanup): {
++     bb14 (cleanup): {
 +         goto -> bb12;
 +     }
 + 
-+     bb16: {
-+         drop(_1) -> [return: bb14, unwind: bb12];
++     bb15: {
++         drop(_1) -> [return: bb13, unwind: bb12];
 +     }
 + 
-+     bb17 (cleanup): {
++     bb16 (cleanup): {
 +         drop(_1) -> [return: bb12, unwind terminate];
 +     }
 + 
-+     bb18: {
++     bb17: {
 +         _10 = discriminant(_1);
-+         switchInt(move _10) -> [0: bb14, otherwise: bb16];
++         switchInt(move _10) -> [0: bb13, otherwise: bb15];
 +     }
 + 
-+     bb19: {
-+         switchInt(_7) -> [0: bb14, otherwise: bb18];
++     bb18: {
++         switchInt(_7) -> [0: bb13, otherwise: bb17];
 +     }
 + 
-+     bb20 (cleanup): {
++     bb19 (cleanup): {
 +         _11 = discriminant(_1);
-+         switchInt(move _11) -> [0: bb15, otherwise: bb17];
++         switchInt(move _11) -> [0: bb14, otherwise: bb16];
 +     }
 + 
-+     bb21 (cleanup): {
-+         switchInt(_7) -> [0: bb12, otherwise: bb20];
++     bb20 (cleanup): {
++         switchInt(_7) -> [0: bb12, otherwise: bb19];
       }
   }
   
diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff
index b647455aeec..f61632728ba 100644
--- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff
+++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff
@@ -13,13 +13,16 @@
       let mut _8: usize;
       let mut _9: usize;
       let mut _10: bool;
-      let mut _11: !;
+      let mut _14: !;
       scope 1 {
           debug v => _2;
+          let _11: &T;
+          let _12: &T;
+          let _13: &T;
           scope 2 {
-              debug v1 => &(*_2)[0 of 3];
-              debug v2 => &(*_2)[1 of 3];
-              debug v3 => &(*_2)[2 of 3];
+              debug v1 => _11;
+              debug v2 => _12;
+              debug v3 => _13;
           }
       }
   
@@ -39,10 +42,19 @@
       }
   
       bb1: {
-          _11 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind unreachable;
+          _14 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind unreachable;
       }
   
       bb2: {
+          StorageLive(_11);
+          _11 = &(*_2)[0 of 3];
+          StorageLive(_12);
+          _12 = &(*_2)[1 of 3];
+          StorageLive(_13);
+          _13 = &(*_2)[2 of 3];
+          StorageDead(_13);
+          StorageDead(_12);
+          StorageDead(_11);
           StorageDead(_4);
           return;
       }
diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff
index b02be61d031..f6c337be10f 100644
--- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff
+++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff
@@ -13,13 +13,16 @@
       let mut _8: usize;
       let mut _9: usize;
       let mut _10: bool;
-      let mut _11: !;
+      let mut _14: !;
       scope 1 {
           debug v => _2;
+          let _11: &T;
+          let _12: &T;
+          let _13: &T;
           scope 2 {
-              debug v1 => &(*_2)[0 of 3];
-              debug v2 => &(*_2)[1 of 3];
-              debug v3 => &(*_2)[2 of 3];
+              debug v1 => _11;
+              debug v2 => _12;
+              debug v3 => _13;
           }
       }
   
@@ -39,10 +42,19 @@
       }
   
       bb1: {
-          _11 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind continue;
+          _14 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind continue;
       }
   
       bb2: {
+          StorageLive(_11);
+          _11 = &(*_2)[0 of 3];
+          StorageLive(_12);
+          _12 = &(*_2)[1 of 3];
+          StorageLive(_13);
+          _13 = &(*_2)[2 of 3];
+          StorageDead(_13);
+          StorageDead(_12);
+          StorageDead(_11);
           StorageDead(_4);
           return;
       }
diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir
index a7a14ea645b..f8c85941813 100644
--- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir
@@ -8,8 +8,9 @@ fn num_to_digit(_1: char) -> u32 {
         debug self => _1;
         debug radix => const 8_u32;
         let _2: std::option::Option<u32>;
+        let mut _7: &std::option::Option<u32>;
         scope 2 (inlined Option::<u32>::is_some) {
-            debug self => &_2;
+            debug self => _7;
             let mut _3: isize;
         }
     }
@@ -23,12 +24,14 @@ fn num_to_digit(_1: char) -> u32 {
     }
 
     bb0: {
+        StorageLive(_7);
         StorageLive(_2);
         _2 = char::methods::<impl char>::to_digit(_1, const 8_u32) -> [return: bb1, unwind unreachable];
     }
 
     bb1: {
         _3 = discriminant(_2);
+        StorageDead(_7);
         StorageDead(_2);
         switchInt(move _3) -> [1: bb2, otherwise: bb7];
     }
diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir
index 5f8c6f7283c..df7392edc50 100644
--- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir
@@ -8,8 +8,9 @@ fn num_to_digit(_1: char) -> u32 {
         debug self => _1;
         debug radix => const 8_u32;
         let _2: std::option::Option<u32>;
+        let mut _7: &std::option::Option<u32>;
         scope 2 (inlined Option::<u32>::is_some) {
-            debug self => &_2;
+            debug self => _7;
             let mut _3: isize;
         }
     }
@@ -23,12 +24,14 @@ fn num_to_digit(_1: char) -> u32 {
     }
 
     bb0: {
+        StorageLive(_7);
         StorageLive(_2);
         _2 = char::methods::<impl char>::to_digit(_1, const 8_u32) -> [return: bb1, unwind continue];
     }
 
     bb1: {
         _3 = discriminant(_2);
+        StorageDead(_7);
         StorageDead(_2);
         switchInt(move _3) -> [1: bb2, otherwise: bb7];
     }
diff --git a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir
index 9be41bff3ca..b2ea96f033e 100644
--- a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir
@@ -10,13 +10,14 @@ fn step_forward(_1: u32, _2: usize) -> u32 {
         let _3: std::option::Option<u32>;
         let mut _6: bool;
         let mut _7: u32;
+        let mut _8: &std::option::Option<u32>;
         scope 2 {
         }
         scope 3 (inlined Option::<u32>::is_none) {
-            debug self => &_3;
+            debug self => _8;
             let mut _5: bool;
             scope 4 (inlined Option::<u32>::is_some) {
-                debug self => &_3;
+                debug self => _8;
                 let mut _4: isize;
             }
         }
@@ -28,6 +29,7 @@ fn step_forward(_1: u32, _2: usize) -> u32 {
 
     bb0: {
         StorageLive(_6);
+        StorageLive(_8);
         StorageLive(_3);
         _3 = <u32 as Step>::forward_checked(_1, _2) -> [return: bb1, unwind continue];
     }
@@ -39,6 +41,7 @@ fn step_forward(_1: u32, _2: usize) -> u32 {
         _6 = Not(move _5);
         StorageDead(_5);
         StorageDead(_3);
+        StorageDead(_8);
         switchInt(move _6) -> [0: bb3, otherwise: bb2];
     }
 
diff --git a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir
index 07a57a7b578..940b9ae1156 100644
--- a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir
@@ -10,6 +10,7 @@ fn filter_mapped(_1: impl Iterator<Item = T>, _2: impl Fn(T) -> Option<U>) -> ()
     let mut _8: std::option::Option<U>;
     let mut _9: isize;
     let _11: ();
+    let mut _12: &mut std::iter::FilterMap<impl Iterator<Item = T>, impl Fn(T) -> Option<U>>;
     scope 1 {
         debug iter => _5;
         let _10: U;
@@ -17,7 +18,7 @@ fn filter_mapped(_1: impl Iterator<Item = T>, _2: impl Fn(T) -> Option<U>) -> ()
             debug x => _10;
         }
         scope 4 (inlined <FilterMap<impl Iterator<Item = T>, impl Fn(T) -> Option<U>> as Iterator>::next) {
-            debug self => &_5;
+            debug self => _12;
             let mut _6: &mut impl Iterator<Item = T>;
             let mut _7: &mut impl Fn(T) -> Option<U>;
         }
diff --git a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir
index 4c6bcd1bdbd..2e51faeba5a 100644
--- a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir
@@ -4,95 +4,108 @@ fn int_range(_1: usize, _2: usize) -> () {
     debug start => _1;
     debug end => _2;
     let mut _0: ();
-    let mut _3: usize;
-    let mut _6: std::option::Option<usize>;
-    let mut _9: isize;
-    let _11: ();
+    let mut _3: std::ops::Range<usize>;
+    let mut _4: std::ops::Range<usize>;
+    let mut _8: std::option::Option<usize>;
+    let mut _11: isize;
+    let _13: ();
+    let mut _14: &mut std::ops::Range<usize>;
     scope 1 {
-        debug iter => std::ops::Range<usize>{ .0 => _3, .1 => _2, };
-        let _10: usize;
+        debug iter => _4;
+        let _12: usize;
         scope 2 {
-            debug i => _10;
+            debug i => _12;
         }
         scope 4 (inlined iter::range::<impl Iterator for std::ops::Range<usize>>::next) {
-            debug self => &std::ops::Range<usize>{ .0 => _3, .1 => _2, };
+            debug self => _14;
             scope 5 (inlined <std::ops::Range<usize> as iter::range::RangeIteratorImpl>::spec_next) {
-                debug self => &std::ops::Range<usize>{ .0 => _3, .1 => _2, };
-                let mut _5: bool;
-                let _7: usize;
-                let mut _8: usize;
+                debug self => _14;
+                let mut _7: bool;
+                let _9: usize;
+                let mut _10: usize;
+                let mut _15: &usize;
+                let mut _16: &usize;
                 scope 6 {
-                    debug old => _7;
+                    debug old => _9;
                     scope 7 {
                     }
                 }
                 scope 8 (inlined cmp::impls::<impl PartialOrd for usize>::lt) {
-                    debug self => &_3;
-                    debug other => &_2;
-                    let mut _4: usize;
+                    debug self => _15;
+                    debug other => _16;
+                    let mut _5: usize;
+                    let mut _6: usize;
                 }
             }
         }
     }
     scope 3 (inlined <std::ops::Range<usize> as IntoIterator>::into_iter) {
-        debug self => std::ops::Range<usize>{ .0 => _1, .1 => _2, };
+        debug self => _3;
     }
 
     bb0: {
-        StorageLive(_3);
-        _3 = _1;
+        _3 = std::ops::Range::<usize> { start: _1, end: _2 };
+        StorageLive(_4);
+        _4 = move _3;
         goto -> bb1;
     }
 
     bb1: {
-        StorageLive(_6);
+        StorageLive(_8);
+        StorageLive(_9);
         StorageLive(_7);
+        StorageLive(_15);
+        StorageLive(_16);
         StorageLive(_5);
-        StorageLive(_4);
-        _4 = _3;
-        _5 = Lt(move _4, _2);
-        StorageDead(_4);
-        switchInt(move _5) -> [0: bb2, otherwise: bb3];
+        _5 = (_4.0: usize);
+        StorageLive(_6);
+        _6 = (_4.1: usize);
+        _7 = Lt(move _5, move _6);
+        StorageDead(_6);
+        StorageDead(_5);
+        StorageDead(_16);
+        StorageDead(_15);
+        switchInt(move _7) -> [0: bb2, otherwise: bb3];
     }
 
     bb2: {
-        _6 = Option::<usize>::None;
+        _8 = Option::<usize>::None;
         goto -> bb5;
     }
 
     bb3: {
-        _7 = _3;
-        StorageLive(_8);
-        _8 = <usize as Step>::forward_unchecked(_7, const 1_usize) -> [return: bb4, unwind continue];
+        _9 = (_4.0: usize);
+        StorageLive(_10);
+        _10 = <usize as Step>::forward_unchecked(_9, const 1_usize) -> [return: bb4, unwind continue];
     }
 
     bb4: {
-        _3 = move _8;
-        StorageDead(_8);
-        _6 = Option::<usize>::Some(_7);
+        (_4.0: usize) = move _10;
+        StorageDead(_10);
+        _8 = Option::<usize>::Some(_9);
         goto -> bb5;
     }
 
     bb5: {
-        StorageDead(_5);
         StorageDead(_7);
-        _9 = discriminant(_6);
-        switchInt(move _9) -> [0: bb6, 1: bb7, otherwise: bb9];
+        StorageDead(_9);
+        _11 = discriminant(_8);
+        switchInt(move _11) -> [0: bb6, 1: bb7, otherwise: bb9];
     }
 
     bb6: {
-        StorageDead(_6);
-        StorageDead(_3);
+        StorageDead(_8);
+        StorageDead(_4);
         return;
     }
 
     bb7: {
-        _10 = ((_6 as Some).0: usize);
-        _11 = opaque::<usize>(move _10) -> [return: bb8, unwind continue];
+        _12 = ((_8 as Some).0: usize);
+        _13 = opaque::<usize>(move _12) -> [return: bb8, unwind continue];
     }
 
     bb8: {
-        StorageDead(_6);
+        StorageDead(_8);
         goto -> bb1;
     }
 
diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir
index cdaa3cfc995..d76b46bdd94 100644
--- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir
@@ -5,87 +5,100 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
     debug end => _2;
     debug f => _3;
     let mut _0: ();
-    let mut _4: u32;
-    let mut _7: std::option::Option<u32>;
-    let mut _10: isize;
-    let mut _12: &impl Fn(u32);
-    let mut _13: (u32,);
-    let _14: ();
+    let mut _4: std::ops::Range<u32>;
+    let mut _5: std::ops::Range<u32>;
+    let mut _9: std::option::Option<u32>;
+    let mut _12: isize;
+    let mut _14: &impl Fn(u32);
+    let mut _15: (u32,);
+    let _16: ();
+    let mut _17: &mut std::ops::Range<u32>;
     scope 1 {
-        debug iter => std::ops::Range<u32>{ .0 => _4, .1 => _2, };
-        let _11: u32;
+        debug iter => _5;
+        let _13: u32;
         scope 2 {
-            debug x => _11;
+            debug x => _13;
         }
         scope 4 (inlined iter::range::<impl Iterator for std::ops::Range<u32>>::next) {
-            debug self => &std::ops::Range<u32>{ .0 => _4, .1 => _2, };
+            debug self => _17;
             scope 5 (inlined <std::ops::Range<u32> as iter::range::RangeIteratorImpl>::spec_next) {
-                debug self => &std::ops::Range<u32>{ .0 => _4, .1 => _2, };
-                let mut _6: bool;
-                let _8: u32;
-                let mut _9: u32;
+                debug self => _17;
+                let mut _8: bool;
+                let _10: u32;
+                let mut _11: u32;
+                let mut _18: &u32;
+                let mut _19: &u32;
                 scope 6 {
-                    debug old => _8;
+                    debug old => _10;
                     scope 7 {
                     }
                 }
                 scope 8 (inlined cmp::impls::<impl PartialOrd for u32>::lt) {
-                    debug self => &_4;
-                    debug other => &_2;
-                    let mut _5: u32;
+                    debug self => _18;
+                    debug other => _19;
+                    let mut _6: u32;
+                    let mut _7: u32;
                 }
             }
         }
     }
     scope 3 (inlined <std::ops::Range<u32> as IntoIterator>::into_iter) {
-        debug self => std::ops::Range<u32>{ .0 => _1, .1 => _2, };
+        debug self => _4;
     }
 
     bb0: {
-        StorageLive(_4);
-        _4 = _1;
+        _4 = std::ops::Range::<u32> { start: _1, end: _2 };
+        StorageLive(_5);
+        _5 = move _4;
         goto -> bb1;
     }
 
     bb1: {
-        StorageLive(_7);
+        StorageLive(_9);
+        StorageLive(_10);
         StorageLive(_8);
+        StorageLive(_18);
+        StorageLive(_19);
         StorageLive(_6);
-        StorageLive(_5);
-        _5 = _4;
-        _6 = Lt(move _5, _2);
-        StorageDead(_5);
-        switchInt(move _6) -> [0: bb2, otherwise: bb3];
+        _6 = (_5.0: u32);
+        StorageLive(_7);
+        _7 = (_5.1: u32);
+        _8 = Lt(move _6, move _7);
+        StorageDead(_7);
+        StorageDead(_6);
+        StorageDead(_19);
+        StorageDead(_18);
+        switchInt(move _8) -> [0: bb2, otherwise: bb3];
     }
 
     bb2: {
-        _7 = Option::<u32>::None;
+        _9 = Option::<u32>::None;
         goto -> bb5;
     }
 
     bb3: {
-        _8 = _4;
-        StorageLive(_9);
-        _9 = <u32 as Step>::forward_unchecked(_8, const 1_usize) -> [return: bb4, unwind unreachable];
+        _10 = (_5.0: u32);
+        StorageLive(_11);
+        _11 = <u32 as Step>::forward_unchecked(_10, const 1_usize) -> [return: bb4, unwind unreachable];
     }
 
     bb4: {
-        _4 = move _9;
-        StorageDead(_9);
-        _7 = Option::<u32>::Some(_8);
+        (_5.0: u32) = move _11;
+        StorageDead(_11);
+        _9 = Option::<u32>::Some(_10);
         goto -> bb5;
     }
 
     bb5: {
-        StorageDead(_6);
         StorageDead(_8);
-        _10 = discriminant(_7);
-        switchInt(move _10) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_10);
+        _12 = discriminant(_9);
+        switchInt(move _12) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
-        StorageDead(_7);
-        StorageDead(_4);
+        StorageDead(_9);
+        StorageDead(_5);
         drop(_3) -> [return: bb7, unwind unreachable];
     }
 
@@ -94,18 +107,18 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
     }
 
     bb8: {
-        _11 = ((_7 as Some).0: u32);
-        StorageLive(_12);
-        _12 = &_3;
-        StorageLive(_13);
-        _13 = (_11,);
-        _14 = <impl Fn(u32) as Fn<(u32,)>>::call(move _12, move _13) -> [return: bb9, unwind unreachable];
+        _13 = ((_9 as Some).0: u32);
+        StorageLive(_14);
+        _14 = &_3;
+        StorageLive(_15);
+        _15 = (_13,);
+        _16 = <impl Fn(u32) as Fn<(u32,)>>::call(move _14, move _15) -> [return: bb9, unwind unreachable];
     }
 
     bb9: {
-        StorageDead(_13);
-        StorageDead(_12);
-        StorageDead(_7);
+        StorageDead(_15);
+        StorageDead(_14);
+        StorageDead(_9);
         goto -> bb1;
     }
 
diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir
index c4e56ea3b23..4d7c017dad4 100644
--- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir
@@ -5,87 +5,100 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
     debug end => _2;
     debug f => _3;
     let mut _0: ();
-    let mut _4: u32;
-    let mut _7: std::option::Option<u32>;
-    let mut _10: isize;
-    let mut _12: &impl Fn(u32);
-    let mut _13: (u32,);
-    let _14: ();
+    let mut _4: std::ops::Range<u32>;
+    let mut _5: std::ops::Range<u32>;
+    let mut _9: std::option::Option<u32>;
+    let mut _12: isize;
+    let mut _14: &impl Fn(u32);
+    let mut _15: (u32,);
+    let _16: ();
+    let mut _17: &mut std::ops::Range<u32>;
     scope 1 {
-        debug iter => std::ops::Range<u32>{ .0 => _4, .1 => _2, };
-        let _11: u32;
+        debug iter => _5;
+        let _13: u32;
         scope 2 {
-            debug x => _11;
+            debug x => _13;
         }
         scope 4 (inlined iter::range::<impl Iterator for std::ops::Range<u32>>::next) {
-            debug self => &std::ops::Range<u32>{ .0 => _4, .1 => _2, };
+            debug self => _17;
             scope 5 (inlined <std::ops::Range<u32> as iter::range::RangeIteratorImpl>::spec_next) {
-                debug self => &std::ops::Range<u32>{ .0 => _4, .1 => _2, };
-                let mut _6: bool;
-                let _8: u32;
-                let mut _9: u32;
+                debug self => _17;
+                let mut _8: bool;
+                let _10: u32;
+                let mut _11: u32;
+                let mut _18: &u32;
+                let mut _19: &u32;
                 scope 6 {
-                    debug old => _8;
+                    debug old => _10;
                     scope 7 {
                     }
                 }
                 scope 8 (inlined cmp::impls::<impl PartialOrd for u32>::lt) {
-                    debug self => &_4;
-                    debug other => &_2;
-                    let mut _5: u32;
+                    debug self => _18;
+                    debug other => _19;
+                    let mut _6: u32;
+                    let mut _7: u32;
                 }
             }
         }
     }
     scope 3 (inlined <std::ops::Range<u32> as IntoIterator>::into_iter) {
-        debug self => std::ops::Range<u32>{ .0 => _1, .1 => _2, };
+        debug self => _4;
     }
 
     bb0: {
-        StorageLive(_4);
-        _4 = _1;
+        _4 = std::ops::Range::<u32> { start: _1, end: _2 };
+        StorageLive(_5);
+        _5 = move _4;
         goto -> bb1;
     }
 
     bb1: {
-        StorageLive(_7);
+        StorageLive(_9);
+        StorageLive(_10);
         StorageLive(_8);
+        StorageLive(_18);
+        StorageLive(_19);
         StorageLive(_6);
-        StorageLive(_5);
-        _5 = _4;
-        _6 = Lt(move _5, _2);
-        StorageDead(_5);
-        switchInt(move _6) -> [0: bb2, otherwise: bb3];
+        _6 = (_5.0: u32);
+        StorageLive(_7);
+        _7 = (_5.1: u32);
+        _8 = Lt(move _6, move _7);
+        StorageDead(_7);
+        StorageDead(_6);
+        StorageDead(_19);
+        StorageDead(_18);
+        switchInt(move _8) -> [0: bb2, otherwise: bb3];
     }
 
     bb2: {
-        _7 = Option::<u32>::None;
+        _9 = Option::<u32>::None;
         goto -> bb5;
     }
 
     bb3: {
-        _8 = _4;
-        StorageLive(_9);
-        _9 = <u32 as Step>::forward_unchecked(_8, const 1_usize) -> [return: bb4, unwind: bb11];
+        _10 = (_5.0: u32);
+        StorageLive(_11);
+        _11 = <u32 as Step>::forward_unchecked(_10, const 1_usize) -> [return: bb4, unwind: bb11];
     }
 
     bb4: {
-        _4 = move _9;
-        StorageDead(_9);
-        _7 = Option::<u32>::Some(_8);
+        (_5.0: u32) = move _11;
+        StorageDead(_11);
+        _9 = Option::<u32>::Some(_10);
         goto -> bb5;
     }
 
     bb5: {
-        StorageDead(_6);
         StorageDead(_8);
-        _10 = discriminant(_7);
-        switchInt(move _10) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_10);
+        _12 = discriminant(_9);
+        switchInt(move _12) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
-        StorageDead(_7);
-        StorageDead(_4);
+        StorageDead(_9);
+        StorageDead(_5);
         drop(_3) -> [return: bb7, unwind continue];
     }
 
@@ -94,18 +107,18 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
     }
 
     bb8: {
-        _11 = ((_7 as Some).0: u32);
-        StorageLive(_12);
-        _12 = &_3;
-        StorageLive(_13);
-        _13 = (_11,);
-        _14 = <impl Fn(u32) as Fn<(u32,)>>::call(move _12, move _13) -> [return: bb9, unwind: bb11];
+        _13 = ((_9 as Some).0: u32);
+        StorageLive(_14);
+        _14 = &_3;
+        StorageLive(_15);
+        _15 = (_13,);
+        _16 = <impl Fn(u32) as Fn<(u32,)>>::call(move _14, move _15) -> [return: bb9, unwind: bb11];
     }
 
     bb9: {
-        StorageDead(_13);
-        StorageDead(_12);
-        StorageDead(_7);
+        StorageDead(_15);
+        StorageDead(_14);
+        StorageDead(_9);
         goto -> bb1;
     }
 
diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir
index 14fd049ede8..7360aa3e698 100644
--- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir
@@ -10,14 +10,16 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> {
             let mut _4: bool;
             let _5: u32;
             let mut _6: u32;
+            let mut _7: &u32;
+            let mut _8: &u32;
             scope 3 {
                 debug old => _5;
                 scope 4 {
                 }
             }
             scope 5 (inlined cmp::impls::<impl PartialOrd for u32>::lt) {
-                debug self => &((*_1).0: u32);
-                debug other => &((*_1).1: u32);
+                debug self => _7;
+                debug other => _8;
                 let mut _2: u32;
                 let mut _3: u32;
             }
@@ -27,6 +29,8 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> {
     bb0: {
         StorageLive(_5);
         StorageLive(_4);
+        StorageLive(_7);
+        StorageLive(_8);
         StorageLive(_2);
         _2 = ((*_1).0: u32);
         StorageLive(_3);
@@ -34,6 +38,8 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> {
         _4 = Lt(move _2, move _3);
         StorageDead(_3);
         StorageDead(_2);
+        StorageDead(_8);
+        StorageDead(_7);
         switchInt(move _4) -> [0: bb1, otherwise: bb2];
     }
 
diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir
index 668a2ac1e20..61957082d8b 100644
--- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir
@@ -10,14 +10,16 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> {
             let mut _4: bool;
             let _5: u32;
             let mut _6: u32;
+            let mut _7: &u32;
+            let mut _8: &u32;
             scope 3 {
                 debug old => _5;
                 scope 4 {
                 }
             }
             scope 5 (inlined cmp::impls::<impl PartialOrd for u32>::lt) {
-                debug self => &((*_1).0: u32);
-                debug other => &((*_1).1: u32);
+                debug self => _7;
+                debug other => _8;
                 let mut _2: u32;
                 let mut _3: u32;
             }
@@ -27,6 +29,8 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> {
     bb0: {
         StorageLive(_5);
         StorageLive(_4);
+        StorageLive(_7);
+        StorageLive(_8);
         StorageLive(_2);
         _2 = ((*_1).0: u32);
         StorageLive(_3);
@@ -34,6 +38,8 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> {
         _4 = Lt(move _2, move _3);
         StorageDead(_3);
         StorageDead(_2);
+        StorageDead(_8);
+        StorageDead(_7);
         switchInt(move _4) -> [0: bb1, otherwise: bb2];
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir
index f9b0c85c852..1488779f93b 100644
--- a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir
@@ -3,138 +3,206 @@
 fn variant_a::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:7:25: 7:39], _2: &&(usize, usize, usize, usize)) -> bool {
     let mut _0: bool;
     let mut _3: &(usize, usize, usize, usize);
-    let mut _4: &(usize, usize, usize, usize);
+    let _4: &usize;
     let mut _5: &(usize, usize, usize, usize);
-    let mut _6: &(usize, usize, usize, usize);
-    let mut _9: bool;
-    let mut _10: bool;
-    let mut _13: bool;
+    let _6: &usize;
+    let mut _7: &(usize, usize, usize, usize);
+    let _8: &usize;
+    let mut _9: &(usize, usize, usize, usize);
+    let _10: &usize;
+    let _11: &usize;
     let mut _16: bool;
     let mut _17: bool;
-    let mut _20: bool;
+    let _18: &usize;
+    let mut _23: bool;
+    let _24: &usize;
+    let mut _29: bool;
+    let mut _30: bool;
+    let _31: &usize;
+    let mut _36: bool;
+    let mut _37: &&usize;
+    let mut _38: &&usize;
+    let mut _39: &&usize;
+    let mut _40: &&usize;
+    let mut _41: &&usize;
+    let mut _42: &&usize;
+    let mut _43: &&usize;
+    let mut _44: &&usize;
     scope 1 {
-        debug a => &((*_3).0: usize);
-        debug b => &((*_4).1: usize);
-        debug c => &((*_5).2: usize);
-        debug d => &((*_6).3: usize);
+        debug a => _4;
+        debug b => _6;
+        debug c => _8;
+        debug d => _10;
         scope 2 (inlined cmp::impls::<impl PartialOrd for &usize>::le) {
-            debug self => &&((*_3).0: usize);
-            debug other => &&((*_5).2: usize);
+            debug self => _37;
+            debug other => _38;
+            let mut _12: &usize;
+            let mut _13: &usize;
             scope 3 (inlined cmp::impls::<impl PartialOrd for usize>::le) {
-                debug self => &((*_3).0: usize);
-                debug other => &((*_5).2: usize);
-                let mut _7: usize;
-                let mut _8: usize;
+                debug self => _12;
+                debug other => _13;
+                let mut _14: usize;
+                let mut _15: usize;
             }
         }
         scope 4 (inlined cmp::impls::<impl PartialOrd for &usize>::le) {
-            debug self => &&((*_5).2: usize);
-            debug other => &&((*_3).0: usize);
+            debug self => _41;
+            debug other => _42;
+            let mut _25: &usize;
+            let mut _26: &usize;
             scope 5 (inlined cmp::impls::<impl PartialOrd for usize>::le) {
-                debug self => &((*_5).2: usize);
-                debug other => &((*_3).0: usize);
-                let mut _14: usize;
-                let mut _15: usize;
+                debug self => _25;
+                debug other => _26;
+                let mut _27: usize;
+                let mut _28: usize;
             }
         }
         scope 6 (inlined cmp::impls::<impl PartialOrd for &usize>::le) {
-            debug self => &&((*_6).3: usize);
-            debug other => &&((*_4).1: usize);
+            debug self => _39;
+            debug other => _40;
+            let mut _19: &usize;
+            let mut _20: &usize;
             scope 7 (inlined cmp::impls::<impl PartialOrd for usize>::le) {
-                debug self => &((*_6).3: usize);
-                debug other => &((*_4).1: usize);
-                let mut _11: usize;
-                let mut _12: usize;
+                debug self => _19;
+                debug other => _20;
+                let mut _21: usize;
+                let mut _22: usize;
             }
         }
         scope 8 (inlined cmp::impls::<impl PartialOrd for &usize>::le) {
-            debug self => &&((*_4).1: usize);
-            debug other => &&((*_6).3: usize);
+            debug self => _43;
+            debug other => _44;
+            let mut _32: &usize;
+            let mut _33: &usize;
             scope 9 (inlined cmp::impls::<impl PartialOrd for usize>::le) {
-                debug self => &((*_4).1: usize);
-                debug other => &((*_6).3: usize);
-                let mut _18: usize;
-                let mut _19: usize;
+                debug self => _32;
+                debug other => _33;
+                let mut _34: usize;
+                let mut _35: usize;
             }
         }
     }
 
     bb0: {
+        StorageLive(_4);
         _3 = deref_copy (*_2);
-        _4 = deref_copy (*_2);
+        _4 = &((*_3).0: usize);
+        StorageLive(_6);
         _5 = deref_copy (*_2);
-        _6 = deref_copy (*_2);
-        StorageLive(_10);
-        StorageLive(_9);
-        StorageLive(_7);
-        _7 = ((*_3).0: usize);
+        _6 = &((*_5).1: usize);
         StorageLive(_8);
-        _8 = ((*_5).2: usize);
-        _9 = Le(move _7, move _8);
-        StorageDead(_8);
-        StorageDead(_7);
-        switchInt(move _9) -> [0: bb1, otherwise: bb2];
+        _7 = deref_copy (*_2);
+        _8 = &((*_7).2: usize);
+        StorageLive(_10);
+        _9 = deref_copy (*_2);
+        _10 = &((*_9).3: usize);
+        StorageLive(_17);
+        StorageLive(_16);
+        StorageLive(_37);
+        StorageLive(_38);
+        StorageLive(_11);
+        _11 = _8;
+        _12 = deref_copy _4;
+        _13 = deref_copy _11;
+        StorageLive(_14);
+        _14 = (*_12);
+        StorageLive(_15);
+        _15 = (*_13);
+        _16 = Le(move _14, move _15);
+        StorageDead(_15);
+        StorageDead(_14);
+        StorageDead(_11);
+        StorageDead(_38);
+        StorageDead(_37);
+        switchInt(move _16) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        _10 = const false;
+        _17 = const false;
         goto -> bb3;
     }
 
     bb2: {
-        StorageLive(_13);
-        StorageLive(_11);
-        _11 = ((*_6).3: usize);
-        StorageLive(_12);
-        _12 = ((*_4).1: usize);
-        _13 = Le(move _11, move _12);
-        StorageDead(_12);
-        StorageDead(_11);
-        _10 = move _13;
+        StorageLive(_23);
+        StorageLive(_39);
+        StorageLive(_40);
+        StorageLive(_18);
+        _18 = _6;
+        _19 = deref_copy _10;
+        _20 = deref_copy _18;
+        StorageLive(_21);
+        _21 = (*_19);
+        StorageLive(_22);
+        _22 = (*_20);
+        _23 = Le(move _21, move _22);
+        StorageDead(_22);
+        StorageDead(_21);
+        StorageDead(_18);
+        StorageDead(_40);
+        StorageDead(_39);
+        _17 = move _23;
         goto -> bb3;
     }
 
     bb3: {
-        StorageDead(_13);
-        StorageDead(_9);
-        switchInt(move _10) -> [0: bb4, otherwise: bb8];
+        StorageDead(_23);
+        StorageDead(_16);
+        switchInt(move _17) -> [0: bb4, otherwise: bb8];
     }
 
     bb4: {
-        StorageLive(_17);
-        StorageLive(_16);
-        StorageLive(_14);
-        _14 = ((*_5).2: usize);
-        StorageLive(_15);
-        _15 = ((*_3).0: usize);
-        _16 = Le(move _14, move _15);
-        StorageDead(_15);
-        StorageDead(_14);
-        switchInt(move _16) -> [0: bb5, otherwise: bb6];
+        StorageLive(_30);
+        StorageLive(_29);
+        StorageLive(_41);
+        StorageLive(_42);
+        StorageLive(_24);
+        _24 = _4;
+        _25 = deref_copy _8;
+        _26 = deref_copy _24;
+        StorageLive(_27);
+        _27 = (*_25);
+        StorageLive(_28);
+        _28 = (*_26);
+        _29 = Le(move _27, move _28);
+        StorageDead(_28);
+        StorageDead(_27);
+        StorageDead(_24);
+        StorageDead(_42);
+        StorageDead(_41);
+        switchInt(move _29) -> [0: bb5, otherwise: bb6];
     }
 
     bb5: {
-        _17 = const false;
+        _30 = const false;
         goto -> bb7;
     }
 
     bb6: {
-        StorageLive(_20);
-        StorageLive(_18);
-        _18 = ((*_4).1: usize);
-        StorageLive(_19);
-        _19 = ((*_6).3: usize);
-        _20 = Le(move _18, move _19);
-        StorageDead(_19);
-        StorageDead(_18);
-        _17 = move _20;
+        StorageLive(_36);
+        StorageLive(_43);
+        StorageLive(_44);
+        StorageLive(_31);
+        _31 = _10;
+        _32 = deref_copy _6;
+        _33 = deref_copy _31;
+        StorageLive(_34);
+        _34 = (*_32);
+        StorageLive(_35);
+        _35 = (*_33);
+        _36 = Le(move _34, move _35);
+        StorageDead(_35);
+        StorageDead(_34);
+        StorageDead(_31);
+        StorageDead(_44);
+        StorageDead(_43);
+        _30 = move _36;
         goto -> bb7;
     }
 
     bb7: {
-        StorageDead(_20);
-        StorageDead(_16);
-        _0 = move _17;
+        StorageDead(_36);
+        StorageDead(_29);
+        _0 = move _30;
         goto -> bb9;
     }
 
@@ -144,8 +212,12 @@ fn variant_a::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:7:25: 7:39], _2
     }
 
     bb9: {
+        StorageDead(_30);
         StorageDead(_17);
         StorageDead(_10);
+        StorageDead(_8);
+        StorageDead(_6);
+        StorageDead(_4);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir
index 901381f070b..4edf4b4fb44 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir
@@ -5,95 +5,109 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     debug f => _2;
     let mut _0: ();
     let mut _3: usize;
-    let mut _4: usize;
-    let mut _7: std::option::Option<usize>;
-    let mut _10: isize;
-    let mut _12: usize;
-    let mut _13: bool;
-    let mut _15: &impl Fn(usize, &T);
-    let mut _16: (usize, &T);
-    let _17: ();
-    let mut _18: usize;
+    let mut _4: std::ops::Range<usize>;
+    let mut _5: std::ops::Range<usize>;
+    let mut _9: std::option::Option<usize>;
+    let mut _12: isize;
+    let mut _14: usize;
+    let mut _15: bool;
+    let mut _17: &impl Fn(usize, &T);
+    let mut _18: (usize, &T);
+    let _19: ();
+    let mut _20: &mut std::ops::Range<usize>;
     scope 1 {
-        debug iter => std::ops::Range<usize>{ .0 => _4, .1 => _3, };
-        let _11: usize;
+        debug iter => _5;
+        let _13: usize;
         scope 2 {
-            debug i => _11;
-            let _14: &T;
+            debug i => _13;
+            let _16: &T;
             scope 3 {
-                debug x => _14;
+                debug x => _16;
             }
         }
         scope 5 (inlined iter::range::<impl Iterator for std::ops::Range<usize>>::next) {
-            debug self => &std::ops::Range<usize>{ .0 => _4, .1 => _3, };
+            debug self => _20;
             scope 6 (inlined <std::ops::Range<usize> as iter::range::RangeIteratorImpl>::spec_next) {
-                debug self => &std::ops::Range<usize>{ .0 => _4, .1 => _3, };
-                let mut _6: bool;
-                let _8: usize;
-                let mut _9: usize;
+                debug self => _20;
+                let mut _8: bool;
+                let _10: usize;
+                let mut _11: usize;
+                let mut _21: &usize;
+                let mut _22: &usize;
                 scope 7 {
-                    debug old => _8;
+                    debug old => _10;
                     scope 8 {
                     }
                 }
                 scope 9 (inlined cmp::impls::<impl PartialOrd for usize>::lt) {
-                    debug self => &_4;
-                    debug other => &_3;
-                    let mut _5: usize;
+                    debug self => _21;
+                    debug other => _22;
+                    let mut _6: usize;
+                    let mut _7: usize;
                 }
             }
         }
     }
     scope 4 (inlined <std::ops::Range<usize> as IntoIterator>::into_iter) {
-        debug self => std::ops::Range<usize>{ .0 => _18, .1 => _3, };
+        debug self => _4;
     }
 
     bb0: {
+        StorageLive(_3);
         _3 = Len((*_1));
-        StorageLive(_4);
-        _4 = const 0_usize;
+        _4 = std::ops::Range::<usize> { start: const 0_usize, end: move _3 };
+        StorageDead(_3);
+        StorageLive(_5);
+        _5 = move _4;
         goto -> bb1;
     }
 
     bb1: {
-        StorageLive(_7);
+        StorageLive(_9);
+        StorageLive(_10);
         StorageLive(_8);
+        StorageLive(_21);
+        StorageLive(_22);
         StorageLive(_6);
-        StorageLive(_5);
-        _5 = _4;
-        _6 = Lt(move _5, _3);
-        StorageDead(_5);
-        switchInt(move _6) -> [0: bb2, otherwise: bb3];
+        _6 = (_5.0: usize);
+        StorageLive(_7);
+        _7 = (_5.1: usize);
+        _8 = Lt(move _6, move _7);
+        StorageDead(_7);
+        StorageDead(_6);
+        StorageDead(_22);
+        StorageDead(_21);
+        switchInt(move _8) -> [0: bb2, otherwise: bb3];
     }
 
     bb2: {
-        _7 = Option::<usize>::None;
+        _9 = Option::<usize>::None;
         goto -> bb5;
     }
 
     bb3: {
-        _8 = _4;
-        StorageLive(_9);
-        _9 = <usize as Step>::forward_unchecked(_8, const 1_usize) -> [return: bb4, unwind unreachable];
+        _10 = (_5.0: usize);
+        StorageLive(_11);
+        _11 = <usize as Step>::forward_unchecked(_10, const 1_usize) -> [return: bb4, unwind unreachable];
     }
 
     bb4: {
-        _4 = move _9;
-        StorageDead(_9);
-        _7 = Option::<usize>::Some(_8);
+        (_5.0: usize) = move _11;
+        StorageDead(_11);
+        _9 = Option::<usize>::Some(_10);
         goto -> bb5;
     }
 
     bb5: {
-        StorageDead(_6);
         StorageDead(_8);
-        _10 = discriminant(_7);
-        switchInt(move _10) -> [0: bb6, 1: bb8, otherwise: bb11];
+        StorageDead(_10);
+        _12 = discriminant(_9);
+        switchInt(move _12) -> [0: bb6, 1: bb8, otherwise: bb11];
     }
 
     bb6: {
-        StorageDead(_7);
-        StorageDead(_4);
+        StorageDead(_9);
+        StorageDead(_5);
         drop(_2) -> [return: bb7, unwind unreachable];
     }
 
@@ -102,25 +116,25 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb8: {
-        _11 = ((_7 as Some).0: usize);
-        _12 = Len((*_1));
-        _13 = Lt(_11, _12);
-        assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> [success: bb9, unwind unreachable];
+        _13 = ((_9 as Some).0: usize);
+        _14 = Len((*_1));
+        _15 = Lt(_13, _14);
+        assert(move _15, "index out of bounds: the length is {} but the index is {}", move _14, _13) -> [success: bb9, unwind unreachable];
     }
 
     bb9: {
-        _14 = &(*_1)[_11];
-        StorageLive(_15);
-        _15 = &_2;
-        StorageLive(_16);
-        _16 = (_11, _14);
-        _17 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _15, move _16) -> [return: bb10, unwind unreachable];
+        _16 = &(*_1)[_13];
+        StorageLive(_17);
+        _17 = &_2;
+        StorageLive(_18);
+        _18 = (_13, _16);
+        _19 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _17, move _18) -> [return: bb10, unwind unreachable];
     }
 
     bb10: {
-        StorageDead(_16);
-        StorageDead(_15);
-        StorageDead(_7);
+        StorageDead(_18);
+        StorageDead(_17);
+        StorageDead(_9);
         goto -> bb1;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir
index a47a73395cf..f7b19e80e44 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir
@@ -5,95 +5,109 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     debug f => _2;
     let mut _0: ();
     let mut _3: usize;
-    let mut _4: usize;
-    let mut _7: std::option::Option<usize>;
-    let mut _10: isize;
-    let mut _12: usize;
-    let mut _13: bool;
-    let mut _15: &impl Fn(usize, &T);
-    let mut _16: (usize, &T);
-    let _17: ();
-    let mut _18: usize;
+    let mut _4: std::ops::Range<usize>;
+    let mut _5: std::ops::Range<usize>;
+    let mut _9: std::option::Option<usize>;
+    let mut _12: isize;
+    let mut _14: usize;
+    let mut _15: bool;
+    let mut _17: &impl Fn(usize, &T);
+    let mut _18: (usize, &T);
+    let _19: ();
+    let mut _20: &mut std::ops::Range<usize>;
     scope 1 {
-        debug iter => std::ops::Range<usize>{ .0 => _4, .1 => _3, };
-        let _11: usize;
+        debug iter => _5;
+        let _13: usize;
         scope 2 {
-            debug i => _11;
-            let _14: &T;
+            debug i => _13;
+            let _16: &T;
             scope 3 {
-                debug x => _14;
+                debug x => _16;
             }
         }
         scope 5 (inlined iter::range::<impl Iterator for std::ops::Range<usize>>::next) {
-            debug self => &std::ops::Range<usize>{ .0 => _4, .1 => _3, };
+            debug self => _20;
             scope 6 (inlined <std::ops::Range<usize> as iter::range::RangeIteratorImpl>::spec_next) {
-                debug self => &std::ops::Range<usize>{ .0 => _4, .1 => _3, };
-                let mut _6: bool;
-                let _8: usize;
-                let mut _9: usize;
+                debug self => _20;
+                let mut _8: bool;
+                let _10: usize;
+                let mut _11: usize;
+                let mut _21: &usize;
+                let mut _22: &usize;
                 scope 7 {
-                    debug old => _8;
+                    debug old => _10;
                     scope 8 {
                     }
                 }
                 scope 9 (inlined cmp::impls::<impl PartialOrd for usize>::lt) {
-                    debug self => &_4;
-                    debug other => &_3;
-                    let mut _5: usize;
+                    debug self => _21;
+                    debug other => _22;
+                    let mut _6: usize;
+                    let mut _7: usize;
                 }
             }
         }
     }
     scope 4 (inlined <std::ops::Range<usize> as IntoIterator>::into_iter) {
-        debug self => std::ops::Range<usize>{ .0 => _18, .1 => _3, };
+        debug self => _4;
     }
 
     bb0: {
+        StorageLive(_3);
         _3 = Len((*_1));
-        StorageLive(_4);
-        _4 = const 0_usize;
+        _4 = std::ops::Range::<usize> { start: const 0_usize, end: move _3 };
+        StorageDead(_3);
+        StorageLive(_5);
+        _5 = move _4;
         goto -> bb1;
     }
 
     bb1: {
-        StorageLive(_7);
+        StorageLive(_9);
+        StorageLive(_10);
         StorageLive(_8);
+        StorageLive(_21);
+        StorageLive(_22);
         StorageLive(_6);
-        StorageLive(_5);
-        _5 = _4;
-        _6 = Lt(move _5, _3);
-        StorageDead(_5);
-        switchInt(move _6) -> [0: bb2, otherwise: bb3];
+        _6 = (_5.0: usize);
+        StorageLive(_7);
+        _7 = (_5.1: usize);
+        _8 = Lt(move _6, move _7);
+        StorageDead(_7);
+        StorageDead(_6);
+        StorageDead(_22);
+        StorageDead(_21);
+        switchInt(move _8) -> [0: bb2, otherwise: bb3];
     }
 
     bb2: {
-        _7 = Option::<usize>::None;
+        _9 = Option::<usize>::None;
         goto -> bb5;
     }
 
     bb3: {
-        _8 = _4;
-        StorageLive(_9);
-        _9 = <usize as Step>::forward_unchecked(_8, const 1_usize) -> [return: bb4, unwind: bb12];
+        _10 = (_5.0: usize);
+        StorageLive(_11);
+        _11 = <usize as Step>::forward_unchecked(_10, const 1_usize) -> [return: bb4, unwind: bb12];
     }
 
     bb4: {
-        _4 = move _9;
-        StorageDead(_9);
-        _7 = Option::<usize>::Some(_8);
+        (_5.0: usize) = move _11;
+        StorageDead(_11);
+        _9 = Option::<usize>::Some(_10);
         goto -> bb5;
     }
 
     bb5: {
-        StorageDead(_6);
         StorageDead(_8);
-        _10 = discriminant(_7);
-        switchInt(move _10) -> [0: bb6, 1: bb8, otherwise: bb11];
+        StorageDead(_10);
+        _12 = discriminant(_9);
+        switchInt(move _12) -> [0: bb6, 1: bb8, otherwise: bb11];
     }
 
     bb6: {
-        StorageDead(_7);
-        StorageDead(_4);
+        StorageDead(_9);
+        StorageDead(_5);
         drop(_2) -> [return: bb7, unwind continue];
     }
 
@@ -102,25 +116,25 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb8: {
-        _11 = ((_7 as Some).0: usize);
-        _12 = Len((*_1));
-        _13 = Lt(_11, _12);
-        assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> [success: bb9, unwind: bb12];
+        _13 = ((_9 as Some).0: usize);
+        _14 = Len((*_1));
+        _15 = Lt(_13, _14);
+        assert(move _15, "index out of bounds: the length is {} but the index is {}", move _14, _13) -> [success: bb9, unwind: bb12];
     }
 
     bb9: {
-        _14 = &(*_1)[_11];
-        StorageLive(_15);
-        _15 = &_2;
-        StorageLive(_16);
-        _16 = (_11, _14);
-        _17 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _15, move _16) -> [return: bb10, unwind: bb12];
+        _16 = &(*_1)[_13];
+        StorageLive(_17);
+        _17 = &_2;
+        StorageLive(_18);
+        _18 = (_13, _16);
+        _19 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _17, move _18) -> [return: bb10, unwind: bb12];
     }
 
     bb10: {
-        StorageDead(_16);
-        StorageDead(_15);
-        StorageDead(_7);
+        StorageDead(_18);
+        StorageDead(_17);
+        StorageDead(_9);
         goto -> bb1;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
index a5df36ca388..549cb4f46a0 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
@@ -12,6 +12,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     let mut _20: &impl Fn(&T);
     let mut _21: (&T,);
     let _22: ();
+    let mut _23: &mut std::iter::Rev<std::slice::Iter<'_, T>>;
     scope 1 {
         debug iter => _15;
         let _19: &T;
@@ -19,7 +20,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
             debug x => _19;
         }
         scope 25 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
-            debug self => &_15;
+            debug self => _23;
             let mut _16: &mut std::slice::Iter<'_, T>;
         }
     }
@@ -48,15 +49,15 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                                     debug ptr => _9;
                                     scope 16 (inlined ptr::mut_ptr::<impl *mut T>::is_null) {
                                         debug self => _9;
-                                        let mut _23: *mut u8;
+                                        let mut _24: *mut u8;
                                         scope 17 {
                                             scope 18 (inlined ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
-                                                debug ptr => _23;
+                                                debug ptr => _24;
                                                 scope 19 (inlined ptr::mut_ptr::<impl *mut u8>::addr) {
-                                                    debug self => _23;
+                                                    debug self => _24;
                                                     scope 20 {
                                                         scope 21 (inlined ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
-                                                            debug self => _23;
+                                                            debug self => _24;
                                                         }
                                                     }
                                                 }
@@ -131,10 +132,10 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
         StorageLive(_9);
         _9 = _4 as *mut T (PtrToPtr);
         StorageLive(_10);
-        StorageLive(_23);
+        StorageLive(_24);
         _10 = _9 as *const T (PointerCoercion(MutToConstPointer));
         _11 = NonNull::<T> { pointer: _10 };
-        StorageDead(_23);
+        StorageDead(_24);
         StorageDead(_10);
         StorageDead(_9);
         StorageLive(_12);
diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
index f681da4d275..43f8806e165 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
@@ -12,6 +12,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     let mut _20: &impl Fn(&T);
     let mut _21: (&T,);
     let _22: ();
+    let mut _23: &mut std::iter::Rev<std::slice::Iter<'_, T>>;
     scope 1 {
         debug iter => _15;
         let _19: &T;
@@ -19,7 +20,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
             debug x => _19;
         }
         scope 25 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
-            debug self => &_15;
+            debug self => _23;
             let mut _16: &mut std::slice::Iter<'_, T>;
         }
     }
@@ -48,15 +49,15 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                                     debug ptr => _9;
                                     scope 16 (inlined ptr::mut_ptr::<impl *mut T>::is_null) {
                                         debug self => _9;
-                                        let mut _23: *mut u8;
+                                        let mut _24: *mut u8;
                                         scope 17 {
                                             scope 18 (inlined ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
-                                                debug ptr => _23;
+                                                debug ptr => _24;
                                                 scope 19 (inlined ptr::mut_ptr::<impl *mut u8>::addr) {
-                                                    debug self => _23;
+                                                    debug self => _24;
                                                     scope 20 {
                                                         scope 21 (inlined ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
-                                                            debug self => _23;
+                                                            debug self => _24;
                                                         }
                                                     }
                                                 }
@@ -131,10 +132,10 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
         StorageLive(_9);
         _9 = _4 as *mut T (PtrToPtr);
         StorageLive(_10);
-        StorageLive(_23);
+        StorageLive(_24);
         _10 = _9 as *const T (PointerCoercion(MutToConstPointer));
         _11 = NonNull::<T> { pointer: _10 };
-        StorageDead(_23);
+        StorageDead(_24);
         StorageDead(_10);
         StorageDead(_9);
         StorageLive(_12);
diff --git a/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff b/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff
index 132f66a1ad3..8fe361f2be4 100644
--- a/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff
@@ -22,27 +22,23 @@
       let _24: &mut u8;
       let mut _25: debuginfo::T;
       scope 1 {
--         debug ref_mut_u8 => _1;
-+         debug ref_mut_u8 => &_2;
+          debug ref_mut_u8 => _1;
           let _3: &u8;
           let mut _28: &debuginfo::T;
           scope 2 {
--             debug field => _3;
-+             debug field => &((*_28).0: u8);
+              debug field => _3;
               let _5: &u8;
               scope 3 {
 -                 debug reborrow => _5;
-+                 debug reborrow => &_2;
++                 debug reborrow => _1;
                   let _9: &i32;
                   let _22: &&&mut u8;
                   let mut _27: &std::option::Option<i32>;
                   scope 4 {
--                     debug variant_field => _9;
-+                     debug variant_field => &(((*_27) as Some).0: i32);
+                      debug variant_field => _9;
                   }
                   scope 5 {
--                     debug constant_index => _19;
-+                     debug constant_index => &(*_11)[1 of 3];
+                      debug constant_index => _19;
                       debug subslice => _20;
                       debug constant_index_from_end => _21;
                       let _19: &i32;
@@ -51,21 +47,20 @@
                       let mut _26: &[i32; 10];
                   }
                   scope 6 {
--                     debug multiple_borrow => _22;
-+                     debug multiple_borrow => &&&(_25.0: u8);
+                      debug multiple_borrow => _22;
                   }
               }
           }
       }
   
       bb0: {
--         StorageLive(_1);
+          StorageLive(_1);
           StorageLive(_2);
           _2 = const 5_u8;
--         _1 = &mut _2;
--         StorageLive(_3);
+          _1 = &mut _2;
+          StorageLive(_3);
           _28 = const _;
--         _3 = &((*_28).0: u8);
+          _3 = &((*_28).0: u8);
 -         StorageLive(_5);
 -         _5 = &(*_1);
 -         StorageLive(_6);
@@ -76,11 +71,11 @@
       }
   
       bb1: {
--         StorageLive(_9);
+          StorageLive(_9);
           _27 = const _;
--         _9 = &(((*_27) as Some).0: i32);
+          _9 = &(((*_27) as Some).0: i32);
 -         _6 = const ();
--         StorageDead(_9);
+          StorageDead(_9);
           goto -> bb4;
       }
   
@@ -118,8 +113,8 @@
       }
   
       bb6: {
--         StorageLive(_19);
--         _19 = &(*_11)[1 of 3];
+          StorageLive(_19);
+          _19 = &(*_11)[1 of 3];
           StorageLive(_20);
           _20 = &(*_11)[2:-1];
           StorageLive(_21);
@@ -127,7 +122,7 @@
 -         _10 = const ();
           StorageDead(_21);
           StorageDead(_20);
--         StorageDead(_19);
+          StorageDead(_19);
           goto -> bb8;
       }
   
@@ -140,23 +135,23 @@
           StorageDead(_12);
           StorageDead(_11);
 -         StorageDead(_10);
--         StorageLive(_22);
--         StorageLive(_23);
--         StorageLive(_24);
+          StorageLive(_22);
+          StorageLive(_23);
+          StorageLive(_24);
           StorageLive(_25);
           _25 = T(const 6_u8);
--         _24 = &mut (_25.0: u8);
--         _23 = &_24;
--         _22 = &_23;
+          _24 = &mut (_25.0: u8);
+          _23 = &_24;
+          _22 = &_23;
           _0 = const ();
           StorageDead(_25);
--         StorageDead(_24);
--         StorageDead(_23);
--         StorageDead(_22);
+          StorageDead(_24);
+          StorageDead(_23);
+          StorageDead(_22);
 -         StorageDead(_5);
--         StorageDead(_3);
+          StorageDead(_3);
           StorageDead(_2);
--         StorageDead(_1);
+          StorageDead(_1);
           return;
       }
   }
diff --git a/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff
index 9ec8f9d78bb..747028e128f 100644
--- a/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff
@@ -13,16 +13,15 @@
           debug x => _1;
           let _2: &mut i32;
           scope 2 {
--             debug xref => _2;
-+             debug xref => &_1;
+              debug xref => _2;
               let _3: *mut i32;
               scope 3 {
 -                 debug xraw => _3;
-+                 debug xraw => &_1;
++                 debug xraw => _2;
                   let _6: &i32;
                   scope 4 {
 -                     debug xshr => _6;
-+                     debug xshr => &_1;
++                     debug xshr => _2;
                       let _7: i32;
                       scope 5 {
                           debug a => _7;
@@ -38,7 +37,7 @@
           StorageLive(_1);
           _1 = const 2_i32;
 -         StorageLive(_2);
--         _2 = &mut _1;
+          _2 = &mut _1;
 -         StorageLive(_3);
 -         StorageLive(_4);
 -         StorageLive(_5);
diff --git a/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff
index f1f77cffd20..1be2ce8d0bb 100644
--- a/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff
@@ -52,8 +52,7 @@
           debug a => _4;
           let _5: &usize;
           scope 2 {
--             debug b => _5;
-+             debug b => &_4;
+              debug b => _5;
               let _6: usize;
               scope 3 {
                   debug c => _6;
@@ -158,12 +157,10 @@
           debug a => _60;
           let _61: &usize;
           scope 30 {
--             debug b => _61;
-+             debug b => &_60;
+              debug b => _61;
               let _62: &&usize;
               scope 31 {
--                 debug d => _62;
-+                 debug d => &&_60;
+                  debug d => _62;
                   let _63: usize;
                   scope 32 {
                       debug c => _63;
@@ -175,12 +172,10 @@
           debug a => _66;
           let mut _67: &usize;
           scope 34 {
--             debug b => _67;
-+             debug b => &_66;
+              debug b => _67;
               let _68: &mut &usize;
               scope 35 {
--                 debug d => _68;
-+                 debug d => &&_66;
+                  debug d => _68;
                   let _69: usize;
                   scope 36 {
                       debug c => _69;
@@ -193,8 +188,8 @@
 -         StorageLive(_3);
           StorageLive(_4);
           _4 = const 5_usize;
--         StorageLive(_5);
--         _5 = &_4;
+          StorageLive(_5);
+          _5 = &_4;
           StorageLive(_6);
 -         _6 = (*_5);
 +         _6 = _4;
@@ -209,7 +204,7 @@
           StorageDead(_7);
 -         _3 = const ();
           StorageDead(_6);
--         StorageDead(_5);
+          StorageDead(_5);
           StorageDead(_4);
 -         StorageDead(_3);
 -         StorageLive(_9);
@@ -394,13 +389,12 @@
 -         StorageLive(_59);
           StorageLive(_60);
           _60 = const 5_usize;
--         StorageLive(_61);
--         _61 = &_60;
--         StorageLive(_62);
--         _62 = &_61;
+          StorageLive(_61);
+          _61 = &_60;
+          StorageLive(_62);
+          _62 = &_61;
           StorageLive(_63);
--         _63 = (*_61);
-+         _63 = _60;
+          _63 = (*_61);
           StorageLive(_64);
           StorageLive(_65);
           _65 = ();
@@ -412,19 +406,18 @@
           StorageDead(_64);
 -         _59 = const ();
           StorageDead(_63);
--         StorageDead(_62);
--         StorageDead(_61);
+          StorageDead(_62);
+          StorageDead(_61);
           StorageDead(_60);
 -         StorageDead(_59);
           StorageLive(_66);
           _66 = const 5_usize;
--         StorageLive(_67);
--         _67 = &_66;
--         StorageLive(_68);
--         _68 = &mut _67;
+          StorageLive(_67);
+          _67 = &_66;
+          StorageLive(_68);
+          _68 = &mut _67;
           StorageLive(_69);
--         _69 = (*_67);
-+         _69 = _66;
+          _69 = (*_67);
           StorageLive(_70);
           StorageLive(_71);
           _71 = ();
@@ -436,8 +429,8 @@
           StorageDead(_70);
           _0 = const ();
           StorageDead(_69);
--         StorageDead(_68);
--         StorageDead(_67);
+          StorageDead(_68);
+          StorageDead(_67);
           StorageDead(_66);
           return;
       }
diff --git a/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff
index 05eab7989df..ce5ddbfdd12 100644
--- a/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff
@@ -45,8 +45,7 @@
               debug a => _4;
               let _5: *const usize;
               scope 3 {
--                 debug b => _5;
-+                 debug b => &_4;
+                  debug b => _5;
                   let _6: usize;
                   scope 4 {
                       debug c => _6;
@@ -175,12 +174,10 @@
               debug a => _58;
               let _59: *const usize;
               scope 39 {
--                 debug b => _59;
-+                 debug b => &_58;
+                  debug b => _59;
                   let _60: *const usize;
                   scope 40 {
--                     debug c => _60;
-+                     debug c => &_58;
+                      debug c => _60;
                       let _61: usize;
                       scope 41 {
                           debug e => _61;
@@ -195,12 +192,10 @@
               debug a => _65;
               let _66: *const usize;
               scope 44 {
--                 debug b => _66;
-+                 debug b => &_65;
+                  debug b => _66;
                   let _67: &*const usize;
                   scope 45 {
--                     debug d => _67;
-+                     debug d => &&_65;
+                      debug d => _67;
                       let _68: usize;
                       scope 46 {
                           debug c => _68;
@@ -215,12 +210,10 @@
               debug a => _71;
               let mut _72: *const usize;
               scope 49 {
--                 debug b => _72;
-+                 debug b => &_71;
+                  debug b => _72;
                   let _73: &mut *const usize;
                   scope 50 {
--                     debug d => _73;
-+                     debug d => &&_71;
+                      debug d => _73;
                       let _74: usize;
                       scope 51 {
                           debug c => _74;
@@ -234,8 +227,8 @@
 -         StorageLive(_3);
           StorageLive(_4);
           _4 = const 5_usize;
--         StorageLive(_5);
--         _5 = &raw const _4;
+          StorageLive(_5);
+          _5 = &raw const _4;
           StorageLive(_6);
 -         _6 = (*_5);
 +         _6 = _4;
@@ -250,7 +243,7 @@
           StorageDead(_7);
 -         _3 = const ();
           StorageDead(_6);
--         StorageDead(_5);
+          StorageDead(_5);
           StorageDead(_4);
 -         StorageDead(_3);
 -         StorageLive(_9);
@@ -427,10 +420,11 @@
 -         StorageLive(_57);
           StorageLive(_58);
           _58 = const 13_usize;
--         StorageLive(_59);
--         _59 = &raw const _58;
--         StorageLive(_60);
+          StorageLive(_59);
+          _59 = &raw const _58;
+          StorageLive(_60);
 -         _60 = &raw const (*_59);
++         _60 = &raw const _58;
           StorageLive(_61);
 -         _61 = (*_60);
 +         _61 = _58;
@@ -445,20 +439,19 @@
           StorageDead(_62);
 -         _57 = const ();
           StorageDead(_61);
--         StorageDead(_60);
--         StorageDead(_59);
+          StorageDead(_60);
+          StorageDead(_59);
           StorageDead(_58);
 -         StorageDead(_57);
 -         StorageLive(_64);
           StorageLive(_65);
           _65 = const 5_usize;
--         StorageLive(_66);
--         _66 = &raw const _65;
--         StorageLive(_67);
--         _67 = &_66;
+          StorageLive(_66);
+          _66 = &raw const _65;
+          StorageLive(_67);
+          _67 = &_66;
           StorageLive(_68);
--         _68 = (*_66);
-+         _68 = _65;
+          _68 = (*_66);
           StorageLive(_69);
           StorageLive(_70);
           _70 = ();
@@ -470,19 +463,18 @@
           StorageDead(_69);
 -         _64 = const ();
           StorageDead(_68);
--         StorageDead(_67);
--         StorageDead(_66);
+          StorageDead(_67);
+          StorageDead(_66);
           StorageDead(_65);
 -         StorageDead(_64);
           StorageLive(_71);
           _71 = const 5_usize;
--         StorageLive(_72);
--         _72 = &raw const _71;
--         StorageLive(_73);
--         _73 = &mut _72;
+          StorageLive(_72);
+          _72 = &raw const _71;
+          StorageLive(_73);
+          _73 = &mut _72;
           StorageLive(_74);
--         _74 = (*_72);
-+         _74 = _71;
+          _74 = (*_72);
           StorageLive(_75);
           StorageLive(_76);
           _76 = ();
@@ -494,8 +486,8 @@
           StorageDead(_75);
           _0 = const ();
           StorageDead(_74);
--         StorageDead(_73);
--         StorageDead(_72);
+          StorageDead(_73);
+          StorageDead(_72);
           StorageDead(_71);
           return;
       }
diff --git a/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff
index ee680fdb3f2..7c7f424bba2 100644
--- a/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff
@@ -52,8 +52,7 @@
           debug a => _4;
           let _5: &mut usize;
           scope 2 {
--             debug b => _5;
-+             debug b => &_4;
+              debug b => _5;
               let _6: usize;
               scope 3 {
                   debug c => _6;
@@ -158,12 +157,10 @@
           debug a => _60;
           let _61: &mut usize;
           scope 30 {
--             debug b => _61;
-+             debug b => &_60;
+              debug b => _61;
               let _62: &&mut usize;
               scope 31 {
--                 debug d => _62;
-+                 debug d => &&_60;
+                  debug d => _62;
                   let _63: usize;
                   scope 32 {
                       debug c => _63;
@@ -175,12 +172,10 @@
           debug a => _66;
           let mut _67: &mut usize;
           scope 34 {
--             debug b => _67;
-+             debug b => &_66;
+              debug b => _67;
               let _68: &mut &mut usize;
               scope 35 {
--                 debug d => _68;
-+                 debug d => &&_66;
+                  debug d => _68;
                   let _69: usize;
                   scope 36 {
                       debug c => _69;
@@ -193,8 +188,8 @@
 -         StorageLive(_3);
           StorageLive(_4);
           _4 = const 5_usize;
--         StorageLive(_5);
--         _5 = &mut _4;
+          StorageLive(_5);
+          _5 = &mut _4;
           StorageLive(_6);
 -         _6 = (*_5);
 +         _6 = _4;
@@ -209,7 +204,7 @@
           StorageDead(_7);
 -         _3 = const ();
           StorageDead(_6);
--         StorageDead(_5);
+          StorageDead(_5);
           StorageDead(_4);
 -         StorageDead(_3);
 -         StorageLive(_9);
@@ -391,13 +386,12 @@
 -         StorageLive(_59);
           StorageLive(_60);
           _60 = const 5_usize;
--         StorageLive(_61);
--         _61 = &mut _60;
--         StorageLive(_62);
--         _62 = &_61;
+          StorageLive(_61);
+          _61 = &mut _60;
+          StorageLive(_62);
+          _62 = &_61;
           StorageLive(_63);
--         _63 = (*_61);
-+         _63 = _60;
+          _63 = (*_61);
           StorageLive(_64);
           StorageLive(_65);
           _65 = ();
@@ -409,19 +403,18 @@
           StorageDead(_64);
 -         _59 = const ();
           StorageDead(_63);
--         StorageDead(_62);
--         StorageDead(_61);
+          StorageDead(_62);
+          StorageDead(_61);
           StorageDead(_60);
 -         StorageDead(_59);
           StorageLive(_66);
           _66 = const 5_usize;
--         StorageLive(_67);
--         _67 = &mut _66;
--         StorageLive(_68);
--         _68 = &mut _67;
+          StorageLive(_67);
+          _67 = &mut _66;
+          StorageLive(_68);
+          _68 = &mut _67;
           StorageLive(_69);
--         _69 = (*_67);
-+         _69 = _66;
+          _69 = (*_67);
           StorageLive(_70);
           StorageLive(_71);
           _71 = ();
@@ -433,8 +426,8 @@
           StorageDead(_70);
           _0 = const ();
           StorageDead(_69);
--         StorageDead(_68);
--         StorageDead(_67);
+          StorageDead(_68);
+          StorageDead(_67);
           StorageDead(_66);
           return;
       }
diff --git a/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff
index fb0ef3184f0..b6b2acc0b43 100644
--- a/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff
@@ -42,8 +42,7 @@
               debug a => _4;
               let _5: *mut usize;
               scope 3 {
--                 debug b => _5;
-+                 debug b => &_4;
+                  debug b => _5;
                   let _6: usize;
                   scope 4 {
                       debug c => _6;
@@ -172,12 +171,10 @@
               debug a => _58;
               let _59: *mut usize;
               scope 39 {
--                 debug b => _59;
-+                 debug b => &_58;
+                  debug b => _59;
                   let _60: &*mut usize;
                   scope 40 {
--                     debug d => _60;
-+                     debug d => &&_58;
+                      debug d => _60;
                       let _61: usize;
                       scope 41 {
                           debug c => _61;
@@ -192,12 +189,10 @@
               debug a => _64;
               let mut _65: *mut usize;
               scope 44 {
--                 debug b => _65;
-+                 debug b => &_64;
+                  debug b => _65;
                   let _66: &mut *mut usize;
                   scope 45 {
--                     debug d => _66;
-+                     debug d => &&_64;
+                      debug d => _66;
                       let _67: usize;
                       scope 46 {
                           debug c => _67;
@@ -211,8 +206,8 @@
 -         StorageLive(_3);
           StorageLive(_4);
           _4 = const 5_usize;
--         StorageLive(_5);
--         _5 = &raw mut _4;
+          StorageLive(_5);
+          _5 = &raw mut _4;
           StorageLive(_6);
 -         _6 = (*_5);
 +         _6 = _4;
@@ -227,7 +222,7 @@
           StorageDead(_7);
 -         _3 = const ();
           StorageDead(_6);
--         StorageDead(_5);
+          StorageDead(_5);
           StorageDead(_4);
 -         StorageDead(_3);
 -         StorageLive(_9);
@@ -401,13 +396,12 @@
 -         StorageLive(_57);
           StorageLive(_58);
           _58 = const 5_usize;
--         StorageLive(_59);
--         _59 = &raw mut _58;
--         StorageLive(_60);
--         _60 = &_59;
+          StorageLive(_59);
+          _59 = &raw mut _58;
+          StorageLive(_60);
+          _60 = &_59;
           StorageLive(_61);
--         _61 = (*_59);
-+         _61 = _58;
+          _61 = (*_59);
           StorageLive(_62);
           StorageLive(_63);
           _63 = ();
@@ -419,19 +413,18 @@
           StorageDead(_62);
 -         _57 = const ();
           StorageDead(_61);
--         StorageDead(_60);
--         StorageDead(_59);
+          StorageDead(_60);
+          StorageDead(_59);
           StorageDead(_58);
 -         StorageDead(_57);
           StorageLive(_64);
           _64 = const 5_usize;
--         StorageLive(_65);
--         _65 = &raw mut _64;
--         StorageLive(_66);
--         _66 = &mut _65;
+          StorageLive(_65);
+          _65 = &raw mut _64;
+          StorageLive(_66);
+          _66 = &mut _65;
           StorageLive(_67);
--         _67 = (*_65);
-+         _67 = _64;
+          _67 = (*_65);
           StorageLive(_68);
           StorageLive(_69);
           _69 = ();
@@ -443,8 +436,8 @@
           StorageDead(_68);
           _0 = const ();
           StorageDead(_67);
--         StorageDead(_66);
--         StorageDead(_65);
+          StorageDead(_66);
+          StorageDead(_65);
           StorageDead(_64);
           return;
       }
diff --git a/tests/mir-opt/reference_prop.rs b/tests/mir-opt/reference_prop.rs
index 4083b45470b..610660131b1 100644
--- a/tests/mir-opt/reference_prop.rs
+++ b/tests/mir-opt/reference_prop.rs
@@ -426,7 +426,7 @@ fn multiple_storage() {
             // As there are multiple `StorageLive` statements for `x`, we cannot know if this `z`'s
             // pointer address is the address of `x`, so do nothing.
             let y = *z;
-            Call(RET, retblock, opaque(y))
+            Call(RET = opaque(y), retblock)
         }
 
         retblock = {
@@ -452,7 +452,7 @@ fn dominate_storage() {
         }
         bb1 = {
             let c = *r;
-            Call(RET, bb2, opaque(c))
+            Call(RET = opaque(c), bb2)
         }
         bb2 = {
             StorageDead(x);
@@ -486,18 +486,18 @@ fn maybe_dead(m: bool) {
         bb1 = {
             StorageDead(x);
             StorageDead(y);
-            Call(RET, bb2, opaque(u))
+            Call(RET = opaque(u), bb2)
         }
         bb2 = {
             // As `x` may be `StorageDead`, `a` may be dangling, so we do nothing.
             let z = *a;
-            Call(RET, bb3, opaque(z))
+            Call(RET = opaque(z), bb3)
         }
         bb3 = {
             // As `y` may be `StorageDead`, `b` may be dangling, so we do nothing.
             // This implies that we also do not substitute `b` in `bb0`.
             let t = *b;
-            Call(RET, retblock, opaque(t))
+            Call(RET = opaque(t), retblock)
         }
         retblock = {
             Return()
diff --git a/tests/run-coverage-rustdoc/doctest.coverage b/tests/run-coverage-rustdoc/doctest.coverage
index 0fce73a6048..07f1e6b3ee5 100644
--- a/tests/run-coverage-rustdoc/doctest.coverage
+++ b/tests/run-coverage-rustdoc/doctest.coverage
@@ -1,115 +1,115 @@
 $DIR/auxiliary/doctest_crate.rs:
-    1|       |/// A function run only from within doctests
-    2|      3|pub fn fn_run_in_doctests(conditional: usize) {
-    3|      3|    match conditional {
-    4|      1|        1 => assert_eq!(1, 1), // this is run,
-    5|      1|        2 => assert_eq!(1, 1), // this,
-    6|      1|        3 => assert_eq!(1, 1), // and this too
-    7|      0|        _ => assert_eq!(1, 2), // however this is not
-    8|       |    }
-    9|      3|}
+   LL|       |/// A function run only from within doctests
+   LL|      3|pub fn fn_run_in_doctests(conditional: usize) {
+   LL|      3|    match conditional {
+   LL|      1|        1 => assert_eq!(1, 1), // this is run,
+   LL|      1|        2 => assert_eq!(1, 1), // this,
+   LL|      1|        3 => assert_eq!(1, 1), // and this too
+   LL|      0|        _ => assert_eq!(1, 2), // however this is not
+   LL|       |    }
+   LL|      3|}
 
 $DIR/doctest.rs:
-    1|       |//! This test ensures that code from doctests is properly re-mapped.
-    2|       |//! See <https://github.com/rust-lang/rust/issues/79417> for more info.
-    3|       |//!
-    4|       |//! Just some random code:
-    5|      1|//! ```
-    6|      1|//! if true {
-    7|       |//!     // this is executed!
-    8|      1|//!     assert_eq!(1, 1);
-    9|       |//! } else {
-   10|       |//!     // this is not!
-   11|      0|//!     assert_eq!(1, 2);
-   12|       |//! }
-   13|      1|//! ```
-   14|       |//!
-   15|       |//! doctest testing external code:
-   16|       |//! ```
-   17|      1|//! extern crate doctest_crate;
-   18|      1|//! doctest_crate::fn_run_in_doctests(1);
-   19|      1|//! ```
-   20|       |//!
-   21|       |//! doctest returning a result:
-   22|      1|//! ```
-   23|      2|//! #[derive(Debug, PartialEq)]
+   LL|       |//! This test ensures that code from doctests is properly re-mapped.
+   LL|       |//! See <https://github.com/rust-lang/rust/issues/79417> for more info.
+   LL|       |//!
+   LL|       |//! Just some random code:
+   LL|      1|//! ```
+   LL|      1|//! if true {
+   LL|       |//!     // this is executed!
+   LL|      1|//!     assert_eq!(1, 1);
+   LL|       |//! } else {
+   LL|       |//!     // this is not!
+   LL|      0|//!     assert_eq!(1, 2);
+   LL|       |//! }
+   LL|      1|//! ```
+   LL|       |//!
+   LL|       |//! doctest testing external code:
+   LL|       |//! ```
+   LL|      1|//! extern crate doctest_crate;
+   LL|      1|//! doctest_crate::fn_run_in_doctests(1);
+   LL|      1|//! ```
+   LL|       |//!
+   LL|       |//! doctest returning a result:
+   LL|      1|//! ```
+   LL|      2|//! #[derive(Debug, PartialEq)]
                        ^1
-   24|      1|//! struct SomeError {
-   25|      1|//!     msg: String,
-   26|      1|//! }
-   27|      1|//! let mut res = Err(SomeError { msg: String::from("a message") });
-   28|      1|//! if res.is_ok() {
-   29|      0|//!     res?;
-   30|       |//! } else {
-   31|      1|//!     if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
-   32|      1|//!         println!("{:?}", res);
-   33|      1|//!     }
+   LL|      1|//! struct SomeError {
+   LL|      1|//!     msg: String,
+   LL|      1|//! }
+   LL|      1|//! let mut res = Err(SomeError { msg: String::from("a message") });
+   LL|      1|//! if res.is_ok() {
+   LL|      0|//!     res?;
+   LL|       |//! } else {
+   LL|      1|//!     if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+   LL|      1|//!         println!("{:?}", res);
+   LL|      1|//!     }
                    ^0
-   34|      1|//!     if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
-   35|      1|//!         res = Ok(1);
-   36|      1|//!     }
+   LL|      1|//!     if *res.as_ref().unwrap_err() == *res.as_ref().unwrap_err() {
+   LL|      1|//!         res = Ok(1);
+   LL|      1|//!     }
                    ^0
-   37|      1|//!     res = Ok(0);
-   38|       |//! }
-   39|       |//! // need to be explicit because rustdoc cant infer the return type
-   40|      1|//! Ok::<(), SomeError>(())
-   41|      1|//! ```
-   42|       |//!
-   43|       |//! doctest with custom main:
-   44|       |//! ```
-   45|      1|//! fn some_func() {
-   46|      1|//!     println!("called some_func()");
-   47|      1|//! }
-   48|       |//!
-   49|      0|//! #[derive(Debug)]
-   50|       |//! struct SomeError;
-   51|       |//!
-   52|       |//! extern crate doctest_crate;
-   53|       |//!
-   54|      1|//! fn doctest_main() -> Result<(), SomeError> {
-   55|      1|//!     some_func();
-   56|      1|//!     doctest_crate::fn_run_in_doctests(2);
-   57|      1|//!     Ok(())
-   58|      1|//! }
-   59|       |//!
-   60|       |//! // this `main` is not shown as covered, as it clashes with all the other
-   61|       |//! // `main` functions that were automatically generated for doctests
-   62|       |//! fn main() -> Result<(), SomeError> {
-   63|       |//!     doctest_main()
-   64|       |//! }
-   65|       |//! ```
-   66|       |// aux-build:doctest_crate.rs
-   67|       |/// doctest attached to fn testing external code:
-   68|       |/// ```
-   69|      1|/// extern crate doctest_crate;
-   70|      1|/// doctest_crate::fn_run_in_doctests(3);
-   71|      1|/// ```
-   72|       |///
-   73|      1|fn main() {
-   74|      1|    if true {
-   75|      1|        assert_eq!(1, 1);
-   76|       |    } else {
-   77|      0|        assert_eq!(1, 2);
-   78|       |    }
-   79|      1|}
-   80|       |
-   81|       |// FIXME(Swatinem): Fix known issue that coverage code region columns need to be offset by the
-   82|       |// doc comment line prefix (`///` or `//!`) and any additional indent (before or after the doc
-   83|       |// comment characters). This test produces `llvm-cov show` results demonstrating the problem.
-   84|       |//
-   85|       |// One of the above tests now includes: `derive(Debug, PartialEq)`, producing an `llvm-cov show`
-   86|       |// result with a distinct count for `Debug`, denoted by `^1`, but the caret points to the wrong
-   87|       |// column. Similarly, the `if` blocks without `else` blocks show `^0`, which should point at, or
-   88|       |// one character past, the `if` block's closing brace. In both cases, these are most likely off
-   89|       |// by the number of characters stripped from the beginning of each doc comment line: indent
-   90|       |// whitespace, if any, doc comment prefix (`//!` in this case) and (I assume) one space character
-   91|       |// (?). Note, when viewing `llvm-cov show` results in `--color` mode, the column offset errors are
-   92|       |// more pronounced, and show up in more places, with background color used to show some distinct
-   93|       |// code regions with different coverage counts.
-   94|       |//
-   95|       |// NOTE: Since the doc comment line prefix may vary, one possible solution is to replace each
-   96|       |// character stripped from the beginning of doc comment lines with a space. This will give coverage
-   97|       |// results the correct column offsets, and I think it should compile correctly, but I don't know
-   98|       |// what affect it might have on diagnostic messages from the compiler, and whether anyone would care
-   99|       |// if the indentation changed. I don't know if there is a more viable solution.
+   LL|      1|//!     res = Ok(0);
+   LL|       |//! }
+   LL|       |//! // need to be explicit because rustdoc cant infer the return type
+   LL|      1|//! Ok::<(), SomeError>(())
+   LL|      1|//! ```
+   LL|       |//!
+   LL|       |//! doctest with custom main:
+   LL|       |//! ```
+   LL|      1|//! fn some_func() {
+   LL|      1|//!     println!("called some_func()");
+   LL|      1|//! }
+   LL|       |//!
+   LL|      0|//! #[derive(Debug)]
+   LL|       |//! struct SomeError;
+   LL|       |//!
+   LL|       |//! extern crate doctest_crate;
+   LL|       |//!
+   LL|      1|//! fn doctest_main() -> Result<(), SomeError> {
+   LL|      1|//!     some_func();
+   LL|      1|//!     doctest_crate::fn_run_in_doctests(2);
+   LL|      1|//!     Ok(())
+   LL|      1|//! }
+   LL|       |//!
+   LL|       |//! // this `main` is not shown as covered, as it clashes with all the other
+   LL|       |//! // `main` functions that were automatically generated for doctests
+   LL|       |//! fn main() -> Result<(), SomeError> {
+   LL|       |//!     doctest_main()
+   LL|       |//! }
+   LL|       |//! ```
+   LL|       |// aux-build:doctest_crate.rs
+   LL|       |/// doctest attached to fn testing external code:
+   LL|       |/// ```
+   LL|      1|/// extern crate doctest_crate;
+   LL|      1|/// doctest_crate::fn_run_in_doctests(3);
+   LL|      1|/// ```
+   LL|       |///
+   LL|      1|fn main() {
+   LL|      1|    if true {
+   LL|      1|        assert_eq!(1, 1);
+   LL|       |    } else {
+   LL|      0|        assert_eq!(1, 2);
+   LL|       |    }
+   LL|      1|}
+   LL|       |
+   LL|       |// FIXME(Swatinem): Fix known issue that coverage code region columns need to be offset by the
+   LL|       |// doc comment line prefix (`///` or `//!`) and any additional indent (before or after the doc
+   LL|       |// comment characters). This test produces `llvm-cov show` results demonstrating the problem.
+   LL|       |//
+   LL|       |// One of the above tests now includes: `derive(Debug, PartialEq)`, producing an `llvm-cov show`
+   LL|       |// result with a distinct count for `Debug`, denoted by `^1`, but the caret points to the wrong
+   LL|       |// column. Similarly, the `if` blocks without `else` blocks show `^0`, which should point at, or
+   LL|       |// one character past, the `if` block's closing brace. In both cases, these are most likely off
+   LL|       |// by the number of characters stripped from the beginning of each doc comment line: indent
+   LL|       |// whitespace, if any, doc comment prefix (`//!` in this case) and (I assume) one space character
+   LL|       |// (?). Note, when viewing `llvm-cov show` results in `--color` mode, the column offset errors are
+   LL|       |// more pronounced, and show up in more places, with background color used to show some distinct
+   LL|       |// code regions with different coverage counts.
+   LL|       |//
+   LL|       |// NOTE: Since the doc comment line prefix may vary, one possible solution is to replace each
+   LL|       |// character stripped from the beginning of doc comment lines with a space. This will give coverage
+   LL|       |// results the correct column offsets, and I think it should compile correctly, but I don't know
+   LL|       |// what affect it might have on diagnostic messages from the compiler, and whether anyone would care
+   LL|       |// if the indentation changed. I don't know if there is a more viable solution.
 
diff --git a/tests/run-coverage/abort.coverage b/tests/run-coverage/abort.coverage
index a71c58d618d..ceef6386780 100644
--- a/tests/run-coverage/abort.coverage
+++ b/tests/run-coverage/abort.coverage
@@ -1,69 +1,69 @@
-    1|       |#![feature(c_unwind)]
-    2|       |#![allow(unused_assignments)]
-    3|       |
-    4|     12|extern "C" fn might_abort(should_abort: bool) {
-    5|     12|    if should_abort {
-    6|      0|        println!("aborting...");
-    7|      0|        panic!("panics and aborts");
-    8|     12|    } else {
-    9|     12|        println!("Don't Panic");
-   10|     12|    }
-   11|     12|}
-   12|       |
-   13|      1|fn main() -> Result<(), u8> {
-   14|      1|    let mut countdown = 10;
-   15|     11|    while countdown > 0 {
-   16|     10|        if countdown < 5 {
-   17|      4|            might_abort(false);
-   18|      6|        }
-   19|       |        // See discussion (below the `Notes` section) on coverage results for the closing brace.
-   20|     10|        if countdown < 5 { might_abort(false); } // Counts for different regions on one line.
+   LL|       |#![feature(c_unwind)]
+   LL|       |#![allow(unused_assignments)]
+   LL|       |
+   LL|     12|extern "C" fn might_abort(should_abort: bool) {
+   LL|     12|    if should_abort {
+   LL|      0|        println!("aborting...");
+   LL|      0|        panic!("panics and aborts");
+   LL|     12|    } else {
+   LL|     12|        println!("Don't Panic");
+   LL|     12|    }
+   LL|     12|}
+   LL|       |
+   LL|      1|fn main() -> Result<(), u8> {
+   LL|      1|    let mut countdown = 10;
+   LL|     11|    while countdown > 0 {
+   LL|     10|        if countdown < 5 {
+   LL|      4|            might_abort(false);
+   LL|      6|        }
+   LL|       |        // See discussion (below the `Notes` section) on coverage results for the closing brace.
+   LL|     10|        if countdown < 5 { might_abort(false); } // Counts for different regions on one line.
                                        ^4                     ^6
-   21|       |        // For the following example, the closing brace is the last character on the line.
-   22|       |        // This shows the character after the closing brace is highlighted, even if that next
-   23|       |        // character is a newline.
-   24|     10|        if countdown < 5 { might_abort(false); }
+   LL|       |        // For the following example, the closing brace is the last character on the line.
+   LL|       |        // This shows the character after the closing brace is highlighted, even if that next
+   LL|       |        // character is a newline.
+   LL|     10|        if countdown < 5 { might_abort(false); }
                                        ^4                     ^6
-   25|     10|        countdown -= 1;
-   26|       |    }
-   27|      1|    Ok(())
-   28|      1|}
-   29|       |
-   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 `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
-   37|       |//      intended"). Coverage results would show no executed coverage regions.
-   38|       |//   6. If `should_abort` is `true` and the program aborts, the program exits with a `132` status
-   39|       |//      (on Linux at least).
-   40|       |
-   41|       |/*
-   42|       |
-   43|       |Expect the following coverage results:
-   44|       |
-   45|       |```text
-   46|       |    16|     11|    while countdown > 0 {
-   47|       |    17|     10|        if countdown < 5 {
-   48|       |    18|      4|            might_abort(false);
-   49|       |    19|      6|        }
-   50|       |```
-   51|       |
-   52|       |This is actually correct.
-   53|       |
-   54|       |The condition `countdown < 5` executed 10 times (10 loop iterations).
-   55|       |
-   56|       |It evaluated to `true` 4 times, and executed the `might_abort()` call.
-   57|       |
-   58|       |It skipped the body of the `might_abort()` call 6 times. If an `if` does not include an explicit
-   59|       |`else`, the coverage implementation injects a counter, at the character immediately after the `if`s
-   60|       |closing brace, to count the "implicit" `else`. This is the only way to capture the coverage of the
-   61|       |non-true condition.
-   62|       |
-   63|       |As another example of why this is important, say the condition was `countdown < 50`, which is always
-   64|       |`true`. In that case, we wouldn't have a test for what happens if `might_abort()` is not called.
-   65|       |The closing brace would have a count of `0`, highlighting the missed coverage.
-   66|       |*/
+   LL|     10|        countdown -= 1;
+   LL|       |    }
+   LL|      1|    Ok(())
+   LL|      1|}
+   LL|       |
+   LL|       |// Notes:
+   LL|       |//   1. Compare this program and its coverage results to those of the similar tests
+   LL|       |//      `panic_unwind.rs` and `try_error_result.rs`.
+   LL|       |//   2. This test confirms the coverage generated when a program includes `UnwindAction::Terminate`.
+   LL|       |//   3. The test does not invoke the abort. By executing to a successful completion, the coverage
+   LL|       |//      results show where the program did and did not execute.
+   LL|       |//   4. If the program actually aborted, the coverage counters would not be saved (which "works as
+   LL|       |//      intended"). Coverage results would show no executed coverage regions.
+   LL|       |//   6. If `should_abort` is `true` and the program aborts, the program exits with a `132` status
+   LL|       |//      (on Linux at least).
+   LL|       |
+   LL|       |/*
+   LL|       |
+   LL|       |Expect the following coverage results:
+   LL|       |
+   LL|       |```text
+   LL|       |    16|     11|    while countdown > 0 {
+   LL|       |    17|     10|        if countdown < 5 {
+   LL|       |    18|      4|            might_abort(false);
+   LL|       |    19|      6|        }
+   LL|       |```
+   LL|       |
+   LL|       |This is actually correct.
+   LL|       |
+   LL|       |The condition `countdown < 5` executed 10 times (10 loop iterations).
+   LL|       |
+   LL|       |It evaluated to `true` 4 times, and executed the `might_abort()` call.
+   LL|       |
+   LL|       |It skipped the body of the `might_abort()` call 6 times. If an `if` does not include an explicit
+   LL|       |`else`, the coverage implementation injects a counter, at the character immediately after the `if`s
+   LL|       |closing brace, to count the "implicit" `else`. This is the only way to capture the coverage of the
+   LL|       |non-true condition.
+   LL|       |
+   LL|       |As another example of why this is important, say the condition was `countdown < 50`, which is always
+   LL|       |`true`. In that case, we wouldn't have a test for what happens if `might_abort()` is not called.
+   LL|       |The closing brace would have a count of `0`, highlighting the missed coverage.
+   LL|       |*/
 
diff --git a/tests/run-coverage/assert.coverage b/tests/run-coverage/assert.coverage
index a7134a149e2..3c6108e436a 100644
--- a/tests/run-coverage/assert.coverage
+++ b/tests/run-coverage/assert.coverage
@@ -1,34 +1,34 @@
-    1|       |#![allow(unused_assignments)]
-    2|       |// failure-status: 101
-    3|       |
-    4|      4|fn might_fail_assert(one_plus_one: u32) {
-    5|      4|    println!("does 1 + 1 = {}?", one_plus_one);
-    6|      4|    assert_eq!(1 + 1, one_plus_one, "the argument was wrong");
+   LL|       |#![allow(unused_assignments)]
+   LL|       |// failure-status: 101
+   LL|       |
+   LL|      4|fn might_fail_assert(one_plus_one: u32) {
+   LL|      4|    println!("does 1 + 1 = {}?", one_plus_one);
+   LL|      4|    assert_eq!(1 + 1, one_plus_one, "the argument was wrong");
                                                   ^1
-    7|      3|}
-    8|       |
-    9|      1|fn main() -> Result<(),u8> {
-   10|      1|    let mut countdown = 10;
-   11|     11|    while countdown > 0 {
-   12|     11|        if countdown == 1 {
-   13|      1|            might_fail_assert(3);
-   14|     10|        } else if countdown < 5 {
-   15|      3|            might_fail_assert(2);
-   16|      6|        }
-   17|     10|        countdown -= 1;
-   18|       |    }
-   19|      0|    Ok(())
-   20|      0|}
-   21|       |
-   22|       |// Notes:
-   23|       |//   1. Compare this program and its coverage results to those of the very similar test
-   24|       |//      `panic_unwind.rs`, and similar tests `abort.rs` and `try_error_result.rs`.
-   25|       |//   2. This test confirms the coverage generated when a program passes or fails an `assert!()` or
-   26|       |//      related `assert_*!()` macro.
-   27|       |//   3. Notably, the `assert` macros *do not* generate `TerminatorKind::Assert`. The macros produce
-   28|       |//      conditional expressions, `TerminatorKind::SwitchInt` branches, and a possible call to
-   29|       |//      `begin_panic_fmt()` (that begins a panic unwind, if the assertion test fails).
-   30|       |//   4. `TerminatoKind::Assert` is, however, also present in the MIR generated for this test
-   31|       |//      (and in many other coverage tests). The `Assert` terminator is typically generated by the
-   32|       |//      Rust compiler to check for runtime failures, such as numeric overflows.
+   LL|      3|}
+   LL|       |
+   LL|      1|fn main() -> Result<(),u8> {
+   LL|      1|    let mut countdown = 10;
+   LL|     11|    while countdown > 0 {
+   LL|     11|        if countdown == 1 {
+   LL|      1|            might_fail_assert(3);
+   LL|     10|        } else if countdown < 5 {
+   LL|      3|            might_fail_assert(2);
+   LL|      6|        }
+   LL|     10|        countdown -= 1;
+   LL|       |    }
+   LL|      0|    Ok(())
+   LL|      0|}
+   LL|       |
+   LL|       |// Notes:
+   LL|       |//   1. Compare this program and its coverage results to those of the very similar test
+   LL|       |//      `panic_unwind.rs`, and similar tests `abort.rs` and `try_error_result.rs`.
+   LL|       |//   2. This test confirms the coverage generated when a program passes or fails an `assert!()` or
+   LL|       |//      related `assert_*!()` macro.
+   LL|       |//   3. Notably, the `assert` macros *do not* generate `TerminatorKind::Assert`. The macros produce
+   LL|       |//      conditional expressions, `TerminatorKind::SwitchInt` branches, and a possible call to
+   LL|       |//      `begin_panic_fmt()` (that begins a panic unwind, if the assertion test fails).
+   LL|       |//   4. `TerminatoKind::Assert` is, however, also present in the MIR generated for this test
+   LL|       |//      (and in many other coverage tests). The `Assert` terminator is typically generated by the
+   LL|       |//      Rust compiler to check for runtime failures, such as numeric overflows.
 
diff --git a/tests/run-coverage/async.coverage b/tests/run-coverage/async.coverage
index 93c1535b06b..07bc16c2d92 100644
--- a/tests/run-coverage/async.coverage
+++ b/tests/run-coverage/async.coverage
@@ -1,139 +1,139 @@
-    1|       |#![allow(unused_assignments, dead_code)]
-    2|       |
-    3|       |// compile-flags: --edition=2018 -C opt-level=1
-    4|       |
-    5|      1|async fn c(x: u8) -> u8 {
-    6|      1|    if x == 8 {
-    7|      1|        1
-    8|       |    } else {
-    9|      0|        0
-   10|       |    }
-   11|      1|}
-   12|       |
-   13|      0|async fn d() -> u8 { 1 }
-   14|       |
-   15|      0|async fn e() -> u8 { 1 } // unused function; executor does not block on `g()`
-   16|       |
-   17|      1|async fn f() -> u8 { 1 }
-   18|       |
-   19|      0|async fn foo() -> [bool; 10] { [false; 10] } // unused function; executor does not block on `h()`
-   20|       |
-   21|      1|pub async fn g(x: u8) {
-   22|      0|    match x {
-   23|      0|        y if e().await == y => (),
-   24|      0|        y if f().await == y => (),
-   25|      0|        _ => (),
-   26|       |    }
-   27|      0|}
-   28|       |
-   29|      1|async fn h(x: usize) { // The function signature is counted when called, but the body is not
-   30|      0|                       // executed (not awaited) so the open brace has a `0` count (at least when
-   31|      0|                       // displayed with `llvm-cov show` in color-mode).
-   32|      0|    match x {
-   33|      0|        y if foo().await[y] => (),
-   34|      0|        _ => (),
-   35|       |    }
-   36|      0|}
-   37|       |
-   38|      1|async fn i(x: u8) { // line coverage is 1, but there are 2 regions:
-   39|      1|                    // (a) the function signature, counted when the function is called; and
-   40|      1|                    // (b) the open brace for the function body, counted once when the body is
-   41|      1|                    // executed asynchronously.
-   42|      1|    match x {
-   43|      1|        y if c(x).await == y + 1 => { d().await; }
+   LL|       |#![allow(unused_assignments, dead_code)]
+   LL|       |
+   LL|       |// compile-flags: --edition=2018 -C opt-level=1
+   LL|       |
+   LL|      1|async fn c(x: u8) -> u8 {
+   LL|      1|    if x == 8 {
+   LL|      1|        1
+   LL|       |    } else {
+   LL|      0|        0
+   LL|       |    }
+   LL|      1|}
+   LL|       |
+   LL|      0|async fn d() -> u8 { 1 }
+   LL|       |
+   LL|      0|async fn e() -> u8 { 1 } // unused function; executor does not block on `g()`
+   LL|       |
+   LL|      1|async fn f() -> u8 { 1 }
+   LL|       |
+   LL|      0|async fn foo() -> [bool; 10] { [false; 10] } // unused function; executor does not block on `h()`
+   LL|       |
+   LL|      1|pub async fn g(x: u8) {
+   LL|      0|    match x {
+   LL|      0|        y if e().await == y => (),
+   LL|      0|        y if f().await == y => (),
+   LL|      0|        _ => (),
+   LL|       |    }
+   LL|      0|}
+   LL|       |
+   LL|      1|async fn h(x: usize) { // The function signature is counted when called, but the body is not
+   LL|      0|                       // executed (not awaited) so the open brace has a `0` count (at least when
+   LL|      0|                       // displayed with `llvm-cov show` in color-mode).
+   LL|      0|    match x {
+   LL|      0|        y if foo().await[y] => (),
+   LL|      0|        _ => (),
+   LL|       |    }
+   LL|      0|}
+   LL|       |
+   LL|      1|async fn i(x: u8) { // line coverage is 1, but there are 2 regions:
+   LL|      1|                    // (a) the function signature, counted when the function is called; and
+   LL|      1|                    // (b) the open brace for the function body, counted once when the body is
+   LL|      1|                    // executed asynchronously.
+   LL|      1|    match x {
+   LL|      1|        y if c(x).await == y + 1 => { d().await; }
                       ^0        ^0                  ^0  ^0
-   44|      1|        y if f().await == y + 1 => (),
+   LL|      1|        y if f().await == y + 1 => (),
                       ^0       ^0                ^0
-   45|      1|        _ => (),
-   46|       |    }
-   47|      1|}
-   48|       |
-   49|      1|fn j(x: u8) {
-   50|      1|    // non-async versions of `c()`, `d()`, and `f()` to make it similar to async `i()`.
-   51|      1|    fn c(x: u8) -> u8 {
-   52|      1|        if x == 8 {
-   53|      1|            1 // This line appears covered, but the 1-character expression span covering the `1`
+   LL|      1|        _ => (),
+   LL|       |    }
+   LL|      1|}
+   LL|       |
+   LL|      1|fn j(x: u8) {
+   LL|      1|    // non-async versions of `c()`, `d()`, and `f()` to make it similar to async `i()`.
+   LL|      1|    fn c(x: u8) -> u8 {
+   LL|      1|        if x == 8 {
+   LL|      1|            1 // This line appears covered, but the 1-character expression span covering the `1`
                           ^0
-   54|      1|              // is not executed. (`llvm-cov show` displays a `^0` below the `1` ). This is because
-   55|      1|              // `fn j()` executes the open brace for the function body, followed by the function's
-   56|      1|              // first executable statement, `match x`. Inner function declarations are not
-   57|      1|              // "visible" to the MIR for `j()`, so the code region counts all lines between the
-   58|      1|              // open brace and the first statement as executed, which is, in a sense, true.
-   59|      1|              // `llvm-cov show` overcomes this kind of situation by showing the actual counts
-   60|      1|              // of the enclosed coverages, (that is, the `1` expression was not executed, and
-   61|      1|              // accurately displays a `0`).
-   62|      1|        } else {
-   63|      1|            0
-   64|      1|        }
-   65|      1|    }
-   66|      1|    fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed
+   LL|      1|              // is not executed. (`llvm-cov show` displays a `^0` below the `1` ). This is because
+   LL|      1|              // `fn j()` executes the open brace for the function body, followed by the function's
+   LL|      1|              // first executable statement, `match x`. Inner function declarations are not
+   LL|      1|              // "visible" to the MIR for `j()`, so the code region counts all lines between the
+   LL|      1|              // open brace and the first statement as executed, which is, in a sense, true.
+   LL|      1|              // `llvm-cov show` overcomes this kind of situation by showing the actual counts
+   LL|      1|              // of the enclosed coverages, (that is, the `1` expression was not executed, and
+   LL|      1|              // accurately displays a `0`).
+   LL|      1|        } else {
+   LL|      1|            0
+   LL|      1|        }
+   LL|      1|    }
+   LL|      1|    fn d() -> u8 { 1 } // inner function is defined in-line, but the function is not executed
                   ^0
-   67|      1|    fn f() -> u8 { 1 }
-   68|      1|    match x {
-   69|      1|        y if c(x) == y + 1 => { d(); }
+   LL|      1|    fn f() -> u8 { 1 }
+   LL|      1|    match x {
+   LL|      1|        y if c(x) == y + 1 => { d(); }
                       ^0                    ^0
-   70|      1|        y if f() == y + 1 => (),
+   LL|      1|        y if f() == y + 1 => (),
                       ^0                   ^0
-   71|      1|        _ => (),
-   72|       |    }
-   73|      1|}
-   74|       |
-   75|      0|fn k(x: u8) { // unused function
-   76|      0|    match x {
-   77|      0|        1 => (),
-   78|      0|        2 => (),
-   79|      0|        _ => (),
-   80|       |    }
-   81|      0|}
-   82|       |
-   83|      1|fn l(x: u8) {
-   84|      1|    match x {
-   85|      0|        1 => (),
-   86|      0|        2 => (),
-   87|      1|        _ => (),
-   88|       |    }
-   89|      1|}
-   90|       |
-   91|      1|async fn m(x: u8) -> u8 { x - 1 }
+   LL|      1|        _ => (),
+   LL|       |    }
+   LL|      1|}
+   LL|       |
+   LL|      0|fn k(x: u8) { // unused function
+   LL|      0|    match x {
+   LL|      0|        1 => (),
+   LL|      0|        2 => (),
+   LL|      0|        _ => (),
+   LL|       |    }
+   LL|      0|}
+   LL|       |
+   LL|      1|fn l(x: u8) {
+   LL|      1|    match x {
+   LL|      0|        1 => (),
+   LL|      0|        2 => (),
+   LL|      1|        _ => (),
+   LL|       |    }
+   LL|      1|}
+   LL|       |
+   LL|      1|async fn m(x: u8) -> u8 { x - 1 }
                                       ^0
-   92|       |
-   93|      1|fn main() {
-   94|      1|    let _ = g(10);
-   95|      1|    let _ = h(9);
-   96|      1|    let mut future = Box::pin(i(8));
-   97|      1|    j(7);
-   98|      1|    l(6);
-   99|      1|    let _ = m(5);
-  100|      1|    executor::block_on(future.as_mut());
-  101|      1|}
-  102|       |
-  103|       |mod executor {
-  104|       |    use core::{
-  105|       |        future::Future,
-  106|       |        pin::Pin,
-  107|       |        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
-  108|       |    };
-  109|       |
-  110|      1|    pub fn block_on<F: Future>(mut future: F) -> F::Output {
-  111|      1|        let mut future = unsafe { Pin::new_unchecked(&mut future) };
-  112|      1|        use std::hint::unreachable_unchecked;
-  113|      1|        static VTABLE: RawWakerVTable = RawWakerVTable::new(
-  114|      1|            |_| unsafe { unreachable_unchecked() }, // clone
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    let _ = g(10);
+   LL|      1|    let _ = h(9);
+   LL|      1|    let mut future = Box::pin(i(8));
+   LL|      1|    j(7);
+   LL|      1|    l(6);
+   LL|      1|    let _ = m(5);
+   LL|      1|    executor::block_on(future.as_mut());
+   LL|      1|}
+   LL|       |
+   LL|       |mod executor {
+   LL|       |    use core::{
+   LL|       |        future::Future,
+   LL|       |        pin::Pin,
+   LL|       |        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+   LL|       |    };
+   LL|       |
+   LL|      1|    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+   LL|      1|        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+   LL|      1|        use std::hint::unreachable_unchecked;
+   LL|      1|        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+   LL|      1|            |_| unsafe { unreachable_unchecked() }, // clone
                               ^0
-  115|      1|            |_| unsafe { unreachable_unchecked() }, // wake
+   LL|      1|            |_| unsafe { unreachable_unchecked() }, // wake
                               ^0
-  116|      1|            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+   LL|      1|            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
                               ^0
-  117|      1|            |_| (),
-  118|      1|        );
-  119|      1|        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
-  120|      1|        let mut context = Context::from_waker(&waker);
-  121|       |
-  122|       |        loop {
-  123|      1|            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
-  124|      1|                break val;
-  125|      0|            }
-  126|       |        }
-  127|      1|    }
-  128|       |}
+   LL|      1|            |_| (),
+   LL|      1|        );
+   LL|      1|        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+   LL|      1|        let mut context = Context::from_waker(&waker);
+   LL|       |
+   LL|       |        loop {
+   LL|      1|            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+   LL|      1|                break val;
+   LL|      0|            }
+   LL|       |        }
+   LL|      1|    }
+   LL|       |}
 
diff --git a/tests/run-coverage/async2.coverage b/tests/run-coverage/async2.coverage
index 500dde1f269..7e0139ae036 100644
--- a/tests/run-coverage/async2.coverage
+++ b/tests/run-coverage/async2.coverage
@@ -1,116 +1,116 @@
-    1|       |// compile-flags: --edition=2018
-    2|       |
-    3|       |use core::{
-    4|       |    future::Future,
-    5|       |    marker::Send,
-    6|       |    pin::Pin,
-    7|       |};
-    8|       |
-    9|      1|fn non_async_func() {
-   10|      1|    println!("non_async_func was covered");
-   11|      1|    let b = true;
-   12|      1|    if b {
-   13|      1|        println!("non_async_func println in block");
-   14|      1|    }
+   LL|       |// compile-flags: --edition=2018
+   LL|       |
+   LL|       |use core::{
+   LL|       |    future::Future,
+   LL|       |    marker::Send,
+   LL|       |    pin::Pin,
+   LL|       |};
+   LL|       |
+   LL|      1|fn non_async_func() {
+   LL|      1|    println!("non_async_func was covered");
+   LL|      1|    let b = true;
+   LL|      1|    if b {
+   LL|      1|        println!("non_async_func println in block");
+   LL|      1|    }
                    ^0
-   15|      1|}
-   16|       |
-   17|       |
-   18|       |
-   19|       |
-   20|      1|async fn async_func() {
-   21|      1|    println!("async_func was covered");
-   22|      1|    let b = true;
-   23|      1|    if b {
-   24|      1|        println!("async_func println in block");
-   25|      1|    }
+   LL|      1|}
+   LL|       |
+   LL|       |
+   LL|       |
+   LL|       |
+   LL|      1|async fn async_func() {
+   LL|      1|    println!("async_func was covered");
+   LL|      1|    let b = true;
+   LL|      1|    if b {
+   LL|      1|        println!("async_func println in block");
+   LL|      1|    }
                    ^0
-   26|      1|}
-   27|       |
-   28|       |
-   29|       |
-   30|       |
-   31|      1|async fn async_func_just_println() {
-   32|      1|    println!("async_func_just_println was covered");
-   33|      1|}
-   34|       |
-   35|      1|fn main() {
-   36|      1|    println!("codecovsample::main");
-   37|      1|
-   38|      1|    non_async_func();
-   39|      1|
-   40|      1|    executor::block_on(async_func());
-   41|      1|    executor::block_on(async_func_just_println());
-   42|      1|}
-   43|       |
-   44|       |mod executor {
-   45|       |    use core::{
-   46|       |        future::Future,
-   47|       |        pin::Pin,
-   48|       |        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
-   49|       |    };
-   50|       |
-   51|      2|    pub fn block_on<F: Future>(mut future: F) -> F::Output {
-   52|      2|        let mut future = unsafe { Pin::new_unchecked(&mut future) };
-   53|      2|        use std::hint::unreachable_unchecked;
-   54|      2|        static VTABLE: RawWakerVTable = RawWakerVTable::new(
-   55|      2|            |_| unsafe { unreachable_unchecked() }, // clone
+   LL|      1|}
+   LL|       |
+   LL|       |
+   LL|       |
+   LL|       |
+   LL|      1|async fn async_func_just_println() {
+   LL|      1|    println!("async_func_just_println was covered");
+   LL|      1|}
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    println!("codecovsample::main");
+   LL|      1|
+   LL|      1|    non_async_func();
+   LL|      1|
+   LL|      1|    executor::block_on(async_func());
+   LL|      1|    executor::block_on(async_func_just_println());
+   LL|      1|}
+   LL|       |
+   LL|       |mod executor {
+   LL|       |    use core::{
+   LL|       |        future::Future,
+   LL|       |        pin::Pin,
+   LL|       |        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+   LL|       |    };
+   LL|       |
+   LL|      2|    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+   LL|      2|        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+   LL|      2|        use std::hint::unreachable_unchecked;
+   LL|      2|        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+   LL|      2|            |_| unsafe { unreachable_unchecked() }, // clone
                               ^0
-   56|      2|            |_| unsafe { unreachable_unchecked() }, // wake
+   LL|      2|            |_| unsafe { unreachable_unchecked() }, // wake
                               ^0
-   57|      2|            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+   LL|      2|            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
                               ^0
-   58|      2|            |_| (),
-   59|      2|        );
-   60|      2|        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
-   61|      2|        let mut context = Context::from_waker(&waker);
-   62|       |
-   63|       |        loop {
-   64|      2|            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
-   65|      2|                break val;
-   66|      0|            }
-   67|       |        }
-   68|      2|    }
+   LL|      2|            |_| (),
+   LL|      2|        );
+   LL|      2|        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+   LL|      2|        let mut context = Context::from_waker(&waker);
+   LL|       |
+   LL|       |        loop {
+   LL|      2|            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+   LL|      2|                break val;
+   LL|      0|            }
+   LL|       |        }
+   LL|      2|    }
   ------------------
   | async2::executor::block_on::<async2::async_func::{closure#0}>:
-  |   51|      1|    pub fn block_on<F: Future>(mut future: F) -> F::Output {
-  |   52|      1|        let mut future = unsafe { Pin::new_unchecked(&mut future) };
-  |   53|      1|        use std::hint::unreachable_unchecked;
-  |   54|      1|        static VTABLE: RawWakerVTable = RawWakerVTable::new(
-  |   55|      1|            |_| unsafe { unreachable_unchecked() }, // clone
-  |   56|      1|            |_| unsafe { unreachable_unchecked() }, // wake
-  |   57|      1|            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
-  |   58|      1|            |_| (),
-  |   59|      1|        );
-  |   60|      1|        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
-  |   61|      1|        let mut context = Context::from_waker(&waker);
-  |   62|       |
-  |   63|       |        loop {
-  |   64|      1|            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
-  |   65|      1|                break val;
-  |   66|      0|            }
-  |   67|       |        }
-  |   68|      1|    }
+  |   LL|      1|    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+  |   LL|      1|        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+  |   LL|      1|        use std::hint::unreachable_unchecked;
+  |   LL|      1|        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+  |   LL|      1|            |_| unsafe { unreachable_unchecked() }, // clone
+  |   LL|      1|            |_| unsafe { unreachable_unchecked() }, // wake
+  |   LL|      1|            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+  |   LL|      1|            |_| (),
+  |   LL|      1|        );
+  |   LL|      1|        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+  |   LL|      1|        let mut context = Context::from_waker(&waker);
+  |   LL|       |
+  |   LL|       |        loop {
+  |   LL|      1|            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+  |   LL|      1|                break val;
+  |   LL|      0|            }
+  |   LL|       |        }
+  |   LL|      1|    }
   ------------------
   | async2::executor::block_on::<async2::async_func_just_println::{closure#0}>:
-  |   51|      1|    pub fn block_on<F: Future>(mut future: F) -> F::Output {
-  |   52|      1|        let mut future = unsafe { Pin::new_unchecked(&mut future) };
-  |   53|      1|        use std::hint::unreachable_unchecked;
-  |   54|      1|        static VTABLE: RawWakerVTable = RawWakerVTable::new(
-  |   55|      1|            |_| unsafe { unreachable_unchecked() }, // clone
-  |   56|      1|            |_| unsafe { unreachable_unchecked() }, // wake
-  |   57|      1|            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
-  |   58|      1|            |_| (),
-  |   59|      1|        );
-  |   60|      1|        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
-  |   61|      1|        let mut context = Context::from_waker(&waker);
-  |   62|       |
-  |   63|       |        loop {
-  |   64|      1|            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
-  |   65|      1|                break val;
-  |   66|      0|            }
-  |   67|       |        }
-  |   68|      1|    }
+  |   LL|      1|    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+  |   LL|      1|        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+  |   LL|      1|        use std::hint::unreachable_unchecked;
+  |   LL|      1|        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+  |   LL|      1|            |_| unsafe { unreachable_unchecked() }, // clone
+  |   LL|      1|            |_| unsafe { unreachable_unchecked() }, // wake
+  |   LL|      1|            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+  |   LL|      1|            |_| (),
+  |   LL|      1|        );
+  |   LL|      1|        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+  |   LL|      1|        let mut context = Context::from_waker(&waker);
+  |   LL|       |
+  |   LL|       |        loop {
+  |   LL|      1|            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+  |   LL|      1|                break val;
+  |   LL|      0|            }
+  |   LL|       |        }
+  |   LL|      1|    }
   ------------------
-   69|       |}
+   LL|       |}
 
diff --git a/tests/run-coverage/closure.coverage b/tests/run-coverage/closure.coverage
index 45d36b72e3a..809cf1f4821 100644
--- a/tests/run-coverage/closure.coverage
+++ b/tests/run-coverage/closure.coverage
@@ -1,222 +1,222 @@
-    1|       |#![allow(unused_assignments, unused_variables)]
-    2|       |// compile-flags: -C opt-level=2
-    3|      1|fn main() { // ^^ fix described in rustc_middle/mir/mono.rs
-    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    6|      1|    // dependent conditions.
-    7|      1|    let is_true = std::env::args().len() == 1;
-    8|      1|    let is_false = ! is_true;
-    9|      1|
-   10|      1|    let mut some_string = Some(String::from("the string content"));
-   11|      1|    println!(
-   12|      1|        "The string or alt: {}"
-   13|      1|        ,
-   14|      1|        some_string
-   15|      1|            .
-   16|      1|            unwrap_or_else
-   17|      1|        (
-   18|      1|            ||
-   19|      0|            {
-   20|      0|                let mut countdown = 0;
-   21|      0|                if is_false {
-   22|      0|                    countdown = 10;
-   23|      0|                }
-   24|      0|                "alt string 1".to_owned()
-   25|      1|            }
-   26|      1|        )
-   27|      1|    );
-   28|      1|
-   29|      1|    some_string = Some(String::from("the string content"));
-   30|      1|    let
-   31|      1|        a
-   32|       |    =
-   33|       |        ||
-   34|      0|    {
-   35|      0|        let mut countdown = 0;
-   36|      0|        if is_false {
-   37|      0|            countdown = 10;
-   38|      0|        }
-   39|      0|        "alt string 2".to_owned()
-   40|      0|    };
-   41|      1|    println!(
-   42|      1|        "The string or alt: {}"
-   43|      1|        ,
-   44|      1|        some_string
-   45|      1|            .
-   46|      1|            unwrap_or_else
-   47|      1|        (
-   48|      1|            a
-   49|      1|        )
-   50|      1|    );
-   51|      1|
-   52|      1|    some_string = None;
-   53|      1|    println!(
-   54|      1|        "The string or alt: {}"
-   55|      1|        ,
-   56|      1|        some_string
-   57|      1|            .
-   58|      1|            unwrap_or_else
-   59|      1|        (
-   60|      1|            ||
-   61|      1|            {
-   62|      1|                let mut countdown = 0;
-   63|      1|                if is_false {
-   64|      0|                    countdown = 10;
-   65|      1|                }
-   66|      1|                "alt string 3".to_owned()
-   67|      1|            }
-   68|      1|        )
-   69|      1|    );
-   70|      1|
-   71|      1|    some_string = None;
-   72|      1|    let
-   73|      1|        a
-   74|      1|    =
-   75|      1|        ||
-   76|      1|    {
-   77|      1|        let mut countdown = 0;
-   78|      1|        if is_false {
-   79|      0|            countdown = 10;
-   80|      1|        }
-   81|      1|        "alt string 4".to_owned()
-   82|      1|    };
-   83|      1|    println!(
-   84|      1|        "The string or alt: {}"
-   85|      1|        ,
-   86|      1|        some_string
-   87|      1|            .
-   88|      1|            unwrap_or_else
-   89|      1|        (
-   90|      1|            a
-   91|      1|        )
-   92|      1|    );
-   93|      1|
-   94|      1|    let
-   95|      1|        quote_closure
-   96|      1|    =
-   97|      1|        |val|
-   98|      5|    {
-   99|      5|        let mut countdown = 0;
-  100|      5|        if is_false {
-  101|      0|            countdown = 10;
-  102|      5|        }
-  103|      5|        format!("'{}'", val)
-  104|      5|    };
-  105|      1|    println!(
-  106|      1|        "Repeated, quoted string: {:?}"
-  107|      1|        ,
-  108|      1|        std::iter::repeat("repeat me")
-  109|      1|            .take(5)
-  110|      1|            .map
-  111|      1|        (
-  112|      1|            quote_closure
-  113|      1|        )
-  114|      1|            .collect::<Vec<_>>()
-  115|      1|    );
-  116|      1|
-  117|      1|    let
-  118|      1|        _unused_closure
-  119|       |    =
-  120|       |        |
-  121|       |            mut countdown
-  122|       |        |
-  123|      0|    {
-  124|      0|        if is_false {
-  125|      0|            countdown = 10;
-  126|      0|        }
-  127|      0|        "closure should be unused".to_owned()
-  128|      0|    };
-  129|       |
-  130|      1|    let mut countdown = 10;
-  131|      1|    let _short_unused_closure = | _unused_arg: u8 | countdown += 1;
+   LL|       |#![allow(unused_assignments, unused_variables)]
+   LL|       |// compile-flags: -C opt-level=2
+   LL|      1|fn main() { // ^^ fix described in rustc_middle/mir/mono.rs
+   LL|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+   LL|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   LL|      1|    // dependent conditions.
+   LL|      1|    let is_true = std::env::args().len() == 1;
+   LL|      1|    let is_false = ! is_true;
+   LL|      1|
+   LL|      1|    let mut some_string = Some(String::from("the string content"));
+   LL|      1|    println!(
+   LL|      1|        "The string or alt: {}"
+   LL|      1|        ,
+   LL|      1|        some_string
+   LL|      1|            .
+   LL|      1|            unwrap_or_else
+   LL|      1|        (
+   LL|      1|            ||
+   LL|      0|            {
+   LL|      0|                let mut countdown = 0;
+   LL|      0|                if is_false {
+   LL|      0|                    countdown = 10;
+   LL|      0|                }
+   LL|      0|                "alt string 1".to_owned()
+   LL|      1|            }
+   LL|      1|        )
+   LL|      1|    );
+   LL|      1|
+   LL|      1|    some_string = Some(String::from("the string content"));
+   LL|      1|    let
+   LL|      1|        a
+   LL|       |    =
+   LL|       |        ||
+   LL|      0|    {
+   LL|      0|        let mut countdown = 0;
+   LL|      0|        if is_false {
+   LL|      0|            countdown = 10;
+   LL|      0|        }
+   LL|      0|        "alt string 2".to_owned()
+   LL|      0|    };
+   LL|      1|    println!(
+   LL|      1|        "The string or alt: {}"
+   LL|      1|        ,
+   LL|      1|        some_string
+   LL|      1|            .
+   LL|      1|            unwrap_or_else
+   LL|      1|        (
+   LL|      1|            a
+   LL|      1|        )
+   LL|      1|    );
+   LL|      1|
+   LL|      1|    some_string = None;
+   LL|      1|    println!(
+   LL|      1|        "The string or alt: {}"
+   LL|      1|        ,
+   LL|      1|        some_string
+   LL|      1|            .
+   LL|      1|            unwrap_or_else
+   LL|      1|        (
+   LL|      1|            ||
+   LL|      1|            {
+   LL|      1|                let mut countdown = 0;
+   LL|      1|                if is_false {
+   LL|      0|                    countdown = 10;
+   LL|      1|                }
+   LL|      1|                "alt string 3".to_owned()
+   LL|      1|            }
+   LL|      1|        )
+   LL|      1|    );
+   LL|      1|
+   LL|      1|    some_string = None;
+   LL|      1|    let
+   LL|      1|        a
+   LL|      1|    =
+   LL|      1|        ||
+   LL|      1|    {
+   LL|      1|        let mut countdown = 0;
+   LL|      1|        if is_false {
+   LL|      0|            countdown = 10;
+   LL|      1|        }
+   LL|      1|        "alt string 4".to_owned()
+   LL|      1|    };
+   LL|      1|    println!(
+   LL|      1|        "The string or alt: {}"
+   LL|      1|        ,
+   LL|      1|        some_string
+   LL|      1|            .
+   LL|      1|            unwrap_or_else
+   LL|      1|        (
+   LL|      1|            a
+   LL|      1|        )
+   LL|      1|    );
+   LL|      1|
+   LL|      1|    let
+   LL|      1|        quote_closure
+   LL|      1|    =
+   LL|      1|        |val|
+   LL|      5|    {
+   LL|      5|        let mut countdown = 0;
+   LL|      5|        if is_false {
+   LL|      0|            countdown = 10;
+   LL|      5|        }
+   LL|      5|        format!("'{}'", val)
+   LL|      5|    };
+   LL|      1|    println!(
+   LL|      1|        "Repeated, quoted string: {:?}"
+   LL|      1|        ,
+   LL|      1|        std::iter::repeat("repeat me")
+   LL|      1|            .take(5)
+   LL|      1|            .map
+   LL|      1|        (
+   LL|      1|            quote_closure
+   LL|      1|        )
+   LL|      1|            .collect::<Vec<_>>()
+   LL|      1|    );
+   LL|      1|
+   LL|      1|    let
+   LL|      1|        _unused_closure
+   LL|       |    =
+   LL|       |        |
+   LL|       |            mut countdown
+   LL|       |        |
+   LL|      0|    {
+   LL|      0|        if is_false {
+   LL|      0|            countdown = 10;
+   LL|      0|        }
+   LL|      0|        "closure should be unused".to_owned()
+   LL|      0|    };
+   LL|       |
+   LL|      1|    let mut countdown = 10;
+   LL|      1|    let _short_unused_closure = | _unused_arg: u8 | countdown += 1;
                                                                   ^0
-  132|       |
-  133|       |
-  134|      1|    let short_used_covered_closure_macro = | used_arg: u8 | println!("called");
-  135|      1|    let short_used_not_covered_closure_macro = | used_arg: u8 | println!("not called");
+   LL|       |
+   LL|       |
+   LL|      1|    let short_used_covered_closure_macro = | used_arg: u8 | println!("called");
+   LL|      1|    let short_used_not_covered_closure_macro = | used_arg: u8 | println!("not called");
                                                                               ^0
-  136|      1|    let _short_unused_closure_macro = | _unused_arg: u8 | println!("not called");
+   LL|      1|    let _short_unused_closure_macro = | _unused_arg: u8 | println!("not called");
                                                                         ^0
-  137|       |
-  138|       |
-  139|       |
-  140|       |
-  141|      1|    let _short_unused_closure_block = | _unused_arg: u8 | { println!("not called") };
+   LL|       |
+   LL|       |
+   LL|       |
+   LL|       |
+   LL|      1|    let _short_unused_closure_block = | _unused_arg: u8 | { println!("not called") };
                                                                         ^0
-  142|       |
-  143|      1|    let _shortish_unused_closure = | _unused_arg: u8 | {
-  144|      0|        println!("not called")
-  145|      0|    };
-  146|       |
-  147|      1|    let _as_short_unused_closure = |
-  148|       |        _unused_arg: u8
-  149|      0|    | { println!("not called") };
-  150|       |
-  151|      1|    let _almost_as_short_unused_closure = |
-  152|       |        _unused_arg: u8
-  153|      0|    | { println!("not called") }
-  154|       |    ;
-  155|       |
-  156|       |
-  157|       |
-  158|       |
-  159|       |
-  160|      1|    let _short_unused_closure_line_break_no_block = | _unused_arg: u8 |
-  161|      0|println!("not called")
-  162|       |    ;
-  163|       |
-  164|      1|    let _short_unused_closure_line_break_no_block2 =
-  165|       |        | _unused_arg: u8 |
-  166|      0|            println!(
-  167|      0|                "not called"
-  168|      0|            )
-  169|       |    ;
-  170|       |
-  171|      1|    let short_used_not_covered_closure_line_break_no_block_embedded_branch =
-  172|       |        | _unused_arg: u8 |
-  173|      0|            println!(
-  174|      0|                "not called: {}",
-  175|      0|                if is_true { "check" } else { "me" }
-  176|      0|            )
-  177|       |    ;
-  178|       |
-  179|      1|    let short_used_not_covered_closure_line_break_block_embedded_branch =
-  180|      1|        | _unused_arg: u8 |
-  181|      0|        {
-  182|      0|            println!(
-  183|      0|                "not called: {}",
-  184|      0|                if is_true { "check" } else { "me" }
-  185|       |            )
-  186|      0|        }
-  187|       |    ;
-  188|       |
-  189|      1|    let short_used_covered_closure_line_break_no_block_embedded_branch =
-  190|      1|        | _unused_arg: u8 |
-  191|      1|            println!(
-  192|      1|                "not called: {}",
-  193|      1|                if is_true { "check" } else { "me" }
+   LL|       |
+   LL|      1|    let _shortish_unused_closure = | _unused_arg: u8 | {
+   LL|      0|        println!("not called")
+   LL|      0|    };
+   LL|       |
+   LL|      1|    let _as_short_unused_closure = |
+   LL|       |        _unused_arg: u8
+   LL|      0|    | { println!("not called") };
+   LL|       |
+   LL|      1|    let _almost_as_short_unused_closure = |
+   LL|       |        _unused_arg: u8
+   LL|      0|    | { println!("not called") }
+   LL|       |    ;
+   LL|       |
+   LL|       |
+   LL|       |
+   LL|       |
+   LL|       |
+   LL|      1|    let _short_unused_closure_line_break_no_block = | _unused_arg: u8 |
+   LL|      0|println!("not called")
+   LL|       |    ;
+   LL|       |
+   LL|      1|    let _short_unused_closure_line_break_no_block2 =
+   LL|       |        | _unused_arg: u8 |
+   LL|      0|            println!(
+   LL|      0|                "not called"
+   LL|      0|            )
+   LL|       |    ;
+   LL|       |
+   LL|      1|    let short_used_not_covered_closure_line_break_no_block_embedded_branch =
+   LL|       |        | _unused_arg: u8 |
+   LL|      0|            println!(
+   LL|      0|                "not called: {}",
+   LL|      0|                if is_true { "check" } else { "me" }
+   LL|      0|            )
+   LL|       |    ;
+   LL|       |
+   LL|      1|    let short_used_not_covered_closure_line_break_block_embedded_branch =
+   LL|      1|        | _unused_arg: u8 |
+   LL|      0|        {
+   LL|      0|            println!(
+   LL|      0|                "not called: {}",
+   LL|      0|                if is_true { "check" } else { "me" }
+   LL|       |            )
+   LL|      0|        }
+   LL|       |    ;
+   LL|       |
+   LL|      1|    let short_used_covered_closure_line_break_no_block_embedded_branch =
+   LL|      1|        | _unused_arg: u8 |
+   LL|      1|            println!(
+   LL|      1|                "not called: {}",
+   LL|      1|                if is_true { "check" } else { "me" }
                                                             ^0
-  194|      1|            )
-  195|       |    ;
-  196|       |
-  197|      1|    let short_used_covered_closure_line_break_block_embedded_branch =
-  198|      1|        | _unused_arg: u8 |
-  199|      1|        {
-  200|      1|            println!(
-  201|      1|                "not called: {}",
-  202|      1|                if is_true { "check" } else { "me" }
+   LL|      1|            )
+   LL|       |    ;
+   LL|       |
+   LL|      1|    let short_used_covered_closure_line_break_block_embedded_branch =
+   LL|      1|        | _unused_arg: u8 |
+   LL|      1|        {
+   LL|      1|            println!(
+   LL|      1|                "not called: {}",
+   LL|      1|                if is_true { "check" } else { "me" }
                                                             ^0
-  203|       |            )
-  204|      1|        }
-  205|       |    ;
-  206|       |
-  207|      1|    if is_false {
-  208|      0|        short_used_not_covered_closure_macro(0);
-  209|      0|        short_used_not_covered_closure_line_break_no_block_embedded_branch(0);
-  210|      0|        short_used_not_covered_closure_line_break_block_embedded_branch(0);
-  211|      1|    }
-  212|      1|    short_used_covered_closure_macro(0);
-  213|      1|    short_used_covered_closure_line_break_no_block_embedded_branch(0);
-  214|      1|    short_used_covered_closure_line_break_block_embedded_branch(0);
-  215|      1|}
+   LL|       |            )
+   LL|      1|        }
+   LL|       |    ;
+   LL|       |
+   LL|      1|    if is_false {
+   LL|      0|        short_used_not_covered_closure_macro(0);
+   LL|      0|        short_used_not_covered_closure_line_break_no_block_embedded_branch(0);
+   LL|      0|        short_used_not_covered_closure_line_break_block_embedded_branch(0);
+   LL|      1|    }
+   LL|      1|    short_used_covered_closure_macro(0);
+   LL|      1|    short_used_covered_closure_line_break_no_block_embedded_branch(0);
+   LL|      1|    short_used_covered_closure_line_break_block_embedded_branch(0);
+   LL|      1|}
 
diff --git a/tests/run-coverage/closure_macro.coverage b/tests/run-coverage/closure_macro.coverage
index 87f7014760e..1bfd2013da8 100644
--- a/tests/run-coverage/closure_macro.coverage
+++ b/tests/run-coverage/closure_macro.coverage
@@ -1,42 +1,42 @@
-    1|       |// compile-flags: --edition=2018
-    2|       |#![feature(no_coverage)]
-    3|       |
-    4|       |macro_rules! bail {
-    5|       |    ($msg:literal $(,)?) => {
-    6|       |        if $msg.len() > 0 {
-    7|       |            println!("no msg");
-    8|       |        } else {
-    9|       |            println!($msg);
-   10|       |        }
-   11|       |        return Err(String::from($msg));
-   12|       |    };
-   13|       |}
-   14|       |
-   15|       |macro_rules! on_error {
-   16|       |    ($value:expr, $error_message:expr) => {
-   17|       |        $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
-   18|       |            let message = format!($error_message, e);
-   19|       |            if message.len() > 0 {
-   20|       |                println!("{}", message);
-   21|       |                Ok(String::from("ok"))
-   22|       |            } else {
-   23|       |                bail!("error");
-   24|       |            }
-   25|       |        })
-   26|       |    };
-   27|       |}
-   28|       |
-   29|      1|fn load_configuration_files() -> Result<String, String> {
-   30|      1|    Ok(String::from("config"))
-   31|      1|}
-   32|       |
-   33|      1|pub fn main() -> Result<(), String> {
-   34|      1|    println!("Starting service");
-   35|      1|    let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
+   LL|       |// compile-flags: --edition=2018
+   LL|       |#![feature(no_coverage)]
+   LL|       |
+   LL|       |macro_rules! bail {
+   LL|       |    ($msg:literal $(,)?) => {
+   LL|       |        if $msg.len() > 0 {
+   LL|       |            println!("no msg");
+   LL|       |        } else {
+   LL|       |            println!($msg);
+   LL|       |        }
+   LL|       |        return Err(String::from($msg));
+   LL|       |    };
+   LL|       |}
+   LL|       |
+   LL|       |macro_rules! on_error {
+   LL|       |    ($value:expr, $error_message:expr) => {
+   LL|       |        $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
+   LL|       |            let message = format!($error_message, e);
+   LL|       |            if message.len() > 0 {
+   LL|       |                println!("{}", message);
+   LL|       |                Ok(String::from("ok"))
+   LL|       |            } else {
+   LL|       |                bail!("error");
+   LL|       |            }
+   LL|       |        })
+   LL|       |    };
+   LL|       |}
+   LL|       |
+   LL|      1|fn load_configuration_files() -> Result<String, String> {
+   LL|      1|    Ok(String::from("config"))
+   LL|      1|}
+   LL|       |
+   LL|      1|pub fn main() -> Result<(), String> {
+   LL|      1|    println!("Starting service");
+   LL|      1|    let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
                                                                                                  ^0
-   36|       |
-   37|      1|    let startup_delay_duration = String::from("arg");
-   38|      1|    let _ = (config, startup_delay_duration);
-   39|      1|    Ok(())
-   40|      1|}
+   LL|       |
+   LL|      1|    let startup_delay_duration = String::from("arg");
+   LL|      1|    let _ = (config, startup_delay_duration);
+   LL|      1|    Ok(())
+   LL|      1|}
 
diff --git a/tests/run-coverage/closure_macro_async.coverage b/tests/run-coverage/closure_macro_async.coverage
index 2b5418132c3..0e4365fc797 100644
--- a/tests/run-coverage/closure_macro_async.coverage
+++ b/tests/run-coverage/closure_macro_async.coverage
@@ -1,83 +1,83 @@
-    1|       |// compile-flags: --edition=2018
-    2|       |#![feature(no_coverage)]
-    3|       |
-    4|       |macro_rules! bail {
-    5|       |    ($msg:literal $(,)?) => {
-    6|       |        if $msg.len() > 0 {
-    7|       |            println!("no msg");
-    8|       |        } else {
-    9|       |            println!($msg);
-   10|       |        }
-   11|       |        return Err(String::from($msg));
-   12|       |    };
-   13|       |}
-   14|       |
-   15|       |macro_rules! on_error {
-   16|       |    ($value:expr, $error_message:expr) => {
-   17|       |        $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
-   18|       |            let message = format!($error_message, e);
-   19|       |            if message.len() > 0 {
-   20|       |                println!("{}", message);
-   21|       |                Ok(String::from("ok"))
-   22|       |            } else {
-   23|       |                bail!("error");
-   24|       |            }
-   25|       |        })
-   26|       |    };
-   27|       |}
-   28|       |
-   29|      1|fn load_configuration_files() -> Result<String, String> {
-   30|      1|    Ok(String::from("config"))
-   31|      1|}
-   32|       |
-   33|      1|pub async fn test() -> Result<(), String> {
-   34|      1|    println!("Starting service");
-   35|      1|    let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
+   LL|       |// compile-flags: --edition=2018
+   LL|       |#![feature(no_coverage)]
+   LL|       |
+   LL|       |macro_rules! bail {
+   LL|       |    ($msg:literal $(,)?) => {
+   LL|       |        if $msg.len() > 0 {
+   LL|       |            println!("no msg");
+   LL|       |        } else {
+   LL|       |            println!($msg);
+   LL|       |        }
+   LL|       |        return Err(String::from($msg));
+   LL|       |    };
+   LL|       |}
+   LL|       |
+   LL|       |macro_rules! on_error {
+   LL|       |    ($value:expr, $error_message:expr) => {
+   LL|       |        $value.or_else(|e| { // FIXME(85000): no coverage in closure macros
+   LL|       |            let message = format!($error_message, e);
+   LL|       |            if message.len() > 0 {
+   LL|       |                println!("{}", message);
+   LL|       |                Ok(String::from("ok"))
+   LL|       |            } else {
+   LL|       |                bail!("error");
+   LL|       |            }
+   LL|       |        })
+   LL|       |    };
+   LL|       |}
+   LL|       |
+   LL|      1|fn load_configuration_files() -> Result<String, String> {
+   LL|      1|    Ok(String::from("config"))
+   LL|      1|}
+   LL|       |
+   LL|      1|pub async fn test() -> Result<(), String> {
+   LL|      1|    println!("Starting service");
+   LL|      1|    let config = on_error!(load_configuration_files(), "Error loading configs: {}")?;
                                                                                                  ^0
-   36|       |
-   37|      1|    let startup_delay_duration = String::from("arg");
-   38|      1|    let _ = (config, startup_delay_duration);
-   39|      1|    Ok(())
-   40|      1|}
-   41|       |
-   42|       |#[no_coverage]
-   43|       |fn main() {
-   44|       |    executor::block_on(test());
-   45|       |}
-   46|       |
-   47|       |mod executor {
-   48|       |    use core::{
-   49|       |        future::Future,
-   50|       |        pin::Pin,
-   51|       |        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
-   52|       |    };
-   53|       |
-   54|       |    #[no_coverage]
-   55|       |    pub fn block_on<F: Future>(mut future: F) -> F::Output {
-   56|       |        let mut future = unsafe { Pin::new_unchecked(&mut future) };
-   57|       |        use std::hint::unreachable_unchecked;
-   58|       |        static VTABLE: RawWakerVTable = RawWakerVTable::new(
-   59|       |
-   60|       |            #[no_coverage]
-   61|       |            |_| unsafe { unreachable_unchecked() }, // clone
-   62|       |
-   63|       |            #[no_coverage]
-   64|       |            |_| unsafe { unreachable_unchecked() }, // wake
-   65|       |
-   66|       |            #[no_coverage]
-   67|       |            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
-   68|       |
-   69|       |            #[no_coverage]
-   70|       |            |_| (),
-   71|       |        );
-   72|       |        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
-   73|       |        let mut context = Context::from_waker(&waker);
-   74|       |
-   75|       |        loop {
-   76|       |            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
-   77|       |                break val;
-   78|       |            }
-   79|       |        }
-   80|       |    }
-   81|       |}
+   LL|       |
+   LL|      1|    let startup_delay_duration = String::from("arg");
+   LL|      1|    let _ = (config, startup_delay_duration);
+   LL|      1|    Ok(())
+   LL|      1|}
+   LL|       |
+   LL|       |#[no_coverage]
+   LL|       |fn main() {
+   LL|       |    executor::block_on(test());
+   LL|       |}
+   LL|       |
+   LL|       |mod executor {
+   LL|       |    use core::{
+   LL|       |        future::Future,
+   LL|       |        pin::Pin,
+   LL|       |        task::{Context, Poll, RawWaker, RawWakerVTable, Waker},
+   LL|       |    };
+   LL|       |
+   LL|       |    #[no_coverage]
+   LL|       |    pub fn block_on<F: Future>(mut future: F) -> F::Output {
+   LL|       |        let mut future = unsafe { Pin::new_unchecked(&mut future) };
+   LL|       |        use std::hint::unreachable_unchecked;
+   LL|       |        static VTABLE: RawWakerVTable = RawWakerVTable::new(
+   LL|       |
+   LL|       |            #[no_coverage]
+   LL|       |            |_| unsafe { unreachable_unchecked() }, // clone
+   LL|       |
+   LL|       |            #[no_coverage]
+   LL|       |            |_| unsafe { unreachable_unchecked() }, // wake
+   LL|       |
+   LL|       |            #[no_coverage]
+   LL|       |            |_| unsafe { unreachable_unchecked() }, // wake_by_ref
+   LL|       |
+   LL|       |            #[no_coverage]
+   LL|       |            |_| (),
+   LL|       |        );
+   LL|       |        let waker = unsafe { Waker::from_raw(RawWaker::new(core::ptr::null(), &VTABLE)) };
+   LL|       |        let mut context = Context::from_waker(&waker);
+   LL|       |
+   LL|       |        loop {
+   LL|       |            if let Poll::Ready(val) = future.as_mut().poll(&mut context) {
+   LL|       |                break val;
+   LL|       |            }
+   LL|       |        }
+   LL|       |    }
+   LL|       |}
 
diff --git a/tests/run-coverage/conditions.coverage b/tests/run-coverage/conditions.coverage
index 2d8a98a5d0c..4749c353a64 100644
--- a/tests/run-coverage/conditions.coverage
+++ b/tests/run-coverage/conditions.coverage
@@ -1,94 +1,94 @@
-    1|       |#![allow(unused_assignments, unused_variables)]
-    2|       |
-    3|      1|fn main() {
-    4|      1|    let mut countdown = 0;
-    5|      1|    if true {
-    6|      1|        countdown = 10;
-    7|      1|    }
+   LL|       |#![allow(unused_assignments, unused_variables)]
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    let mut countdown = 0;
+   LL|      1|    if true {
+   LL|      1|        countdown = 10;
+   LL|      1|    }
                    ^0
-    8|       |
-    9|       |    const B: u32 = 100;
-   10|      1|    let x = if countdown > 7 {
-   11|      1|        countdown -= 4;
-   12|      1|        B
-   13|      0|    } else if countdown > 2 {
-   14|      0|        if countdown < 1 || countdown > 5 || countdown != 9 {
-   15|      0|            countdown = 0;
-   16|      0|        }
-   17|      0|        countdown -= 5;
-   18|      0|        countdown
-   19|       |    } else {
-   20|      0|        return;
-   21|       |    };
-   22|       |
-   23|      1|    let mut countdown = 0;
-   24|      1|    if true {
-   25|      1|        countdown = 10;
-   26|      1|    }
+   LL|       |
+   LL|       |    const B: u32 = 100;
+   LL|      1|    let x = if countdown > 7 {
+   LL|      1|        countdown -= 4;
+   LL|      1|        B
+   LL|      0|    } else if countdown > 2 {
+   LL|      0|        if countdown < 1 || countdown > 5 || countdown != 9 {
+   LL|      0|            countdown = 0;
+   LL|      0|        }
+   LL|      0|        countdown -= 5;
+   LL|      0|        countdown
+   LL|       |    } else {
+   LL|      0|        return;
+   LL|       |    };
+   LL|       |
+   LL|      1|    let mut countdown = 0;
+   LL|      1|    if true {
+   LL|      1|        countdown = 10;
+   LL|      1|    }
                    ^0
-   27|       |
-   28|      1|    if countdown > 7 {
-   29|      1|        countdown -= 4;
-   30|      1|    } else if countdown > 2 {
+   LL|       |
+   LL|      1|    if countdown > 7 {
+   LL|      1|        countdown -= 4;
+   LL|      1|    } else if countdown > 2 {
                             ^0
-   31|      0|        if countdown < 1 || countdown > 5 || countdown != 9 {
-   32|      0|            countdown = 0;
-   33|      0|        }
-   34|      0|        countdown -= 5;
-   35|       |    } else {
-   36|      0|        return;
-   37|       |    }
-   38|       |
-   39|      1|    if true {
-   40|      1|        let mut countdown = 0;
-   41|      1|        if true {
-   42|      1|            countdown = 10;
-   43|      1|        }
+   LL|      0|        if countdown < 1 || countdown > 5 || countdown != 9 {
+   LL|      0|            countdown = 0;
+   LL|      0|        }
+   LL|      0|        countdown -= 5;
+   LL|       |    } else {
+   LL|      0|        return;
+   LL|       |    }
+   LL|       |
+   LL|      1|    if true {
+   LL|      1|        let mut countdown = 0;
+   LL|      1|        if true {
+   LL|      1|            countdown = 10;
+   LL|      1|        }
                        ^0
-   44|       |
-   45|      1|        if countdown > 7 {
-   46|      1|            countdown -= 4;
-   47|      1|        }
-   48|      0|        else if countdown > 2 {
-   49|      0|            if countdown < 1 || countdown > 5 || countdown != 9 {
-   50|      0|                countdown = 0;
-   51|      0|            }
-   52|      0|            countdown -= 5;
-   53|       |        } else {
-   54|      0|            return;
-   55|       |        }
-   56|      0|    }
-   57|       |
-   58|       |
-   59|      1|    let mut countdown = 0;
-   60|      1|    if true {
-   61|      1|        countdown = 1;
-   62|      1|    }
+   LL|       |
+   LL|      1|        if countdown > 7 {
+   LL|      1|            countdown -= 4;
+   LL|      1|        }
+   LL|      0|        else if countdown > 2 {
+   LL|      0|            if countdown < 1 || countdown > 5 || countdown != 9 {
+   LL|      0|                countdown = 0;
+   LL|      0|            }
+   LL|      0|            countdown -= 5;
+   LL|       |        } else {
+   LL|      0|            return;
+   LL|       |        }
+   LL|      0|    }
+   LL|       |
+   LL|       |
+   LL|      1|    let mut countdown = 0;
+   LL|      1|    if true {
+   LL|      1|        countdown = 1;
+   LL|      1|    }
                    ^0
-   63|       |
-   64|      1|    let z = if countdown > 7 {
+   LL|       |
+   LL|      1|    let z = if countdown > 7 {
                       ^0
-   65|      0|        countdown -= 4;
-   66|      1|    } else if countdown > 2 {
-   67|      0|        if countdown < 1 || countdown > 5 || countdown != 9 {
-   68|      0|            countdown = 0;
-   69|      0|        }
-   70|      0|        countdown -= 5;
-   71|       |    } else {
-   72|      1|        let should_be_reachable = countdown;
-   73|      1|        println!("reached");
-   74|      1|        return;
-   75|       |    };
-   76|       |
-   77|      0|    let w = if countdown > 7 {
-   78|      0|        countdown -= 4;
-   79|      0|    } else if countdown > 2 {
-   80|      0|        if countdown < 1 || countdown > 5 || countdown != 9 {
-   81|      0|            countdown = 0;
-   82|      0|        }
-   83|      0|        countdown -= 5;
-   84|       |    } else {
-   85|      0|        return;
-   86|       |    };
-   87|      1|}
+   LL|      0|        countdown -= 4;
+   LL|      1|    } else if countdown > 2 {
+   LL|      0|        if countdown < 1 || countdown > 5 || countdown != 9 {
+   LL|      0|            countdown = 0;
+   LL|      0|        }
+   LL|      0|        countdown -= 5;
+   LL|       |    } else {
+   LL|      1|        let should_be_reachable = countdown;
+   LL|      1|        println!("reached");
+   LL|      1|        return;
+   LL|       |    };
+   LL|       |
+   LL|      0|    let w = if countdown > 7 {
+   LL|      0|        countdown -= 4;
+   LL|      0|    } else if countdown > 2 {
+   LL|      0|        if countdown < 1 || countdown > 5 || countdown != 9 {
+   LL|      0|            countdown = 0;
+   LL|      0|        }
+   LL|      0|        countdown -= 5;
+   LL|       |    } else {
+   LL|      0|        return;
+   LL|       |    };
+   LL|      1|}
 
diff --git a/tests/run-coverage/continue.coverage b/tests/run-coverage/continue.coverage
index bf42924b191..4916cac0038 100644
--- a/tests/run-coverage/continue.coverage
+++ b/tests/run-coverage/continue.coverage
@@ -1,70 +1,70 @@
-    1|       |#![allow(unused_assignments, unused_variables)]
-    2|       |
-    3|      1|fn main() {
-    4|      1|    let is_true = std::env::args().len() == 1;
-    5|      1|
-    6|      1|    let mut x = 0;
-    7|     11|    for _ in 0..10 {
-    8|     10|        match is_true {
-    9|       |            true => {
-   10|     10|                continue;
-   11|       |            }
-   12|      0|            _ => {
-   13|      0|                x = 1;
-   14|      0|            }
-   15|      0|        }
-   16|      0|        x = 3;
-   17|       |    }
-   18|     11|    for _ in 0..10 {
-   19|     10|        match is_true {
-   20|      0|            false => {
-   21|      0|                x = 1;
-   22|      0|            }
-   23|       |            _ => {
-   24|     10|                continue;
-   25|       |            }
-   26|       |        }
-   27|      0|        x = 3;
-   28|       |    }
-   29|     11|    for _ in 0..10 {
-   30|     10|        match is_true {
-   31|     10|            true => {
-   32|     10|                x = 1;
-   33|     10|            }
-   34|       |            _ => {
-   35|      0|                continue;
-   36|       |            }
-   37|       |        }
-   38|     10|        x = 3;
-   39|       |    }
-   40|     11|    for _ in 0..10 {
-   41|     10|        if is_true {
-   42|     10|            continue;
-   43|      0|        }
-   44|      0|        x = 3;
-   45|       |    }
-   46|     11|    for _ in 0..10 {
-   47|     10|        match is_true {
-   48|      0|            false => {
-   49|      0|                x = 1;
-   50|      0|            }
-   51|     10|            _ => {
-   52|     10|                let _ = x;
-   53|     10|            }
-   54|       |        }
-   55|     10|        x = 3;
-   56|       |    }
-   57|      1|    for _ in 0..10 {
-   58|      1|        match is_true {
-   59|      0|            false => {
-   60|      0|                x = 1;
-   61|      0|            }
-   62|       |            _ => {
-   63|      1|                break;
-   64|       |            }
-   65|       |        }
-   66|      0|        x = 3;
-   67|       |    }
-   68|      1|    let _ = x;
-   69|      1|}
+   LL|       |#![allow(unused_assignments, unused_variables)]
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    let is_true = std::env::args().len() == 1;
+   LL|      1|
+   LL|      1|    let mut x = 0;
+   LL|     11|    for _ in 0..10 {
+   LL|     10|        match is_true {
+   LL|       |            true => {
+   LL|     10|                continue;
+   LL|       |            }
+   LL|      0|            _ => {
+   LL|      0|                x = 1;
+   LL|      0|            }
+   LL|      0|        }
+   LL|      0|        x = 3;
+   LL|       |    }
+   LL|     11|    for _ in 0..10 {
+   LL|     10|        match is_true {
+   LL|      0|            false => {
+   LL|      0|                x = 1;
+   LL|      0|            }
+   LL|       |            _ => {
+   LL|     10|                continue;
+   LL|       |            }
+   LL|       |        }
+   LL|      0|        x = 3;
+   LL|       |    }
+   LL|     11|    for _ in 0..10 {
+   LL|     10|        match is_true {
+   LL|     10|            true => {
+   LL|     10|                x = 1;
+   LL|     10|            }
+   LL|       |            _ => {
+   LL|      0|                continue;
+   LL|       |            }
+   LL|       |        }
+   LL|     10|        x = 3;
+   LL|       |    }
+   LL|     11|    for _ in 0..10 {
+   LL|     10|        if is_true {
+   LL|     10|            continue;
+   LL|      0|        }
+   LL|      0|        x = 3;
+   LL|       |    }
+   LL|     11|    for _ in 0..10 {
+   LL|     10|        match is_true {
+   LL|      0|            false => {
+   LL|      0|                x = 1;
+   LL|      0|            }
+   LL|     10|            _ => {
+   LL|     10|                let _ = x;
+   LL|     10|            }
+   LL|       |        }
+   LL|     10|        x = 3;
+   LL|       |    }
+   LL|      1|    for _ in 0..10 {
+   LL|      1|        match is_true {
+   LL|      0|            false => {
+   LL|      0|                x = 1;
+   LL|      0|            }
+   LL|       |            _ => {
+   LL|      1|                break;
+   LL|       |            }
+   LL|       |        }
+   LL|      0|        x = 3;
+   LL|       |    }
+   LL|      1|    let _ = x;
+   LL|      1|}
 
diff --git a/tests/run-coverage/dead_code.coverage b/tests/run-coverage/dead_code.coverage
index 09ff14c6f27..5074d8b3c37 100644
--- a/tests/run-coverage/dead_code.coverage
+++ b/tests/run-coverage/dead_code.coverage
@@ -1,39 +1,39 @@
-    1|       |#![allow(unused_assignments, unused_variables)]
-    2|       |
-    3|      0|pub fn unused_pub_fn_not_in_library() {
-    4|      0|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    5|      0|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    6|      0|    // dependent conditions.
-    7|      0|    let is_true = std::env::args().len() == 1;
-    8|      0|
-    9|      0|    let mut countdown = 0;
-   10|      0|    if is_true {
-   11|      0|        countdown = 10;
-   12|      0|    }
-   13|      0|}
-   14|       |
-   15|      0|fn unused_fn() {
-   16|      0|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-   17|      0|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-   18|      0|    // dependent conditions.
-   19|      0|    let is_true = std::env::args().len() == 1;
-   20|      0|
-   21|      0|    let mut countdown = 0;
-   22|      0|    if is_true {
-   23|      0|        countdown = 10;
-   24|      0|    }
-   25|      0|}
-   26|       |
-   27|      1|fn main() {
-   28|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-   29|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-   30|      1|    // dependent conditions.
-   31|      1|    let is_true = std::env::args().len() == 1;
-   32|      1|
-   33|      1|    let mut countdown = 0;
-   34|      1|    if is_true {
-   35|      1|        countdown = 10;
-   36|      1|    }
+   LL|       |#![allow(unused_assignments, unused_variables)]
+   LL|       |
+   LL|      0|pub fn unused_pub_fn_not_in_library() {
+   LL|      0|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+   LL|      0|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   LL|      0|    // dependent conditions.
+   LL|      0|    let is_true = std::env::args().len() == 1;
+   LL|      0|
+   LL|      0|    let mut countdown = 0;
+   LL|      0|    if is_true {
+   LL|      0|        countdown = 10;
+   LL|      0|    }
+   LL|      0|}
+   LL|       |
+   LL|      0|fn unused_fn() {
+   LL|      0|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+   LL|      0|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   LL|      0|    // dependent conditions.
+   LL|      0|    let is_true = std::env::args().len() == 1;
+   LL|      0|
+   LL|      0|    let mut countdown = 0;
+   LL|      0|    if is_true {
+   LL|      0|        countdown = 10;
+   LL|      0|    }
+   LL|      0|}
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+   LL|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   LL|      1|    // dependent conditions.
+   LL|      1|    let is_true = std::env::args().len() == 1;
+   LL|      1|
+   LL|      1|    let mut countdown = 0;
+   LL|      1|    if is_true {
+   LL|      1|        countdown = 10;
+   LL|      1|    }
                    ^0
-   37|      1|}
+   LL|      1|}
 
diff --git a/tests/run-coverage/drop_trait.coverage b/tests/run-coverage/drop_trait.coverage
index 293001e9590..c99b980a339 100644
--- a/tests/run-coverage/drop_trait.coverage
+++ b/tests/run-coverage/drop_trait.coverage
@@ -1,34 +1,34 @@
-    1|       |#![allow(unused_assignments)]
-    2|       |// failure-status: 1
-    3|       |
-    4|       |struct Firework {
-    5|       |    strength: i32,
-    6|       |}
-    7|       |
-    8|       |impl Drop for Firework {
-    9|      2|    fn drop(&mut self) {
-   10|      2|        println!("BOOM times {}!!!", self.strength);
-   11|      2|    }
-   12|       |}
-   13|       |
-   14|      1|fn main() -> Result<(),u8> {
-   15|      1|    let _firecracker = Firework { strength: 1 };
-   16|      1|
-   17|      1|    let _tnt = Firework { strength: 100 };
-   18|      1|
-   19|      1|    if true {
-   20|      1|        println!("Exiting with error...");
-   21|      1|        return Err(1);
-   22|      0|    }
-   23|      0|
-   24|      0|    let _ = Firework { strength: 1000 };
-   25|      0|
-   26|      0|    Ok(())
-   27|      1|}
-   28|       |
-   29|       |// Expected program output:
-   30|       |//   Exiting with error...
-   31|       |//   BOOM times 100!!!
-   32|       |//   BOOM times 1!!!
-   33|       |//   Error: 1
+   LL|       |#![allow(unused_assignments)]
+   LL|       |// failure-status: 1
+   LL|       |
+   LL|       |struct Firework {
+   LL|       |    strength: i32,
+   LL|       |}
+   LL|       |
+   LL|       |impl Drop for Firework {
+   LL|      2|    fn drop(&mut self) {
+   LL|      2|        println!("BOOM times {}!!!", self.strength);
+   LL|      2|    }
+   LL|       |}
+   LL|       |
+   LL|      1|fn main() -> Result<(),u8> {
+   LL|      1|    let _firecracker = Firework { strength: 1 };
+   LL|      1|
+   LL|      1|    let _tnt = Firework { strength: 100 };
+   LL|      1|
+   LL|      1|    if true {
+   LL|      1|        println!("Exiting with error...");
+   LL|      1|        return Err(1);
+   LL|      0|    }
+   LL|      0|
+   LL|      0|    let _ = Firework { strength: 1000 };
+   LL|      0|
+   LL|      0|    Ok(())
+   LL|      1|}
+   LL|       |
+   LL|       |// Expected program output:
+   LL|       |//   Exiting with error...
+   LL|       |//   BOOM times 100!!!
+   LL|       |//   BOOM times 1!!!
+   LL|       |//   Error: 1
 
diff --git a/tests/run-coverage/generator.coverage b/tests/run-coverage/generator.coverage
index 0fb3808ff2e..daba2bea8b8 100644
--- a/tests/run-coverage/generator.coverage
+++ b/tests/run-coverage/generator.coverage
@@ -1,32 +1,32 @@
-    1|       |#![feature(generators, generator_trait)]
-    2|       |
-    3|       |use std::ops::{Generator, GeneratorState};
-    4|       |use std::pin::Pin;
-    5|       |
-    6|       |// The following implementation of a function called from a `yield` statement
-    7|       |// (apparently requiring the Result and the `String` type or constructor)
-    8|       |// creates conditions where the `generator::StateTransform` MIR transform will
-    9|       |// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic
-   10|       |// to handle this condition, and still report dead block coverage.
-   11|      1|fn get_u32(val: bool) -> Result<u32, String> {
-   12|      1|    if val { Ok(1) } else { Err(String::from("some error")) }
+   LL|       |#![feature(generators, generator_trait)]
+   LL|       |
+   LL|       |use std::ops::{Generator, GeneratorState};
+   LL|       |use std::pin::Pin;
+   LL|       |
+   LL|       |// The following implementation of a function called from a `yield` statement
+   LL|       |// (apparently requiring the Result and the `String` type or constructor)
+   LL|       |// creates conditions where the `generator::StateTransform` MIR transform will
+   LL|       |// drop all `Counter` `Coverage` statements from a MIR. `simplify.rs` has logic
+   LL|       |// to handle this condition, and still report dead block coverage.
+   LL|      1|fn get_u32(val: bool) -> Result<u32, String> {
+   LL|      1|    if val { Ok(1) } else { Err(String::from("some error")) }
                                           ^0
-   13|      1|}
-   14|       |
-   15|      1|fn main() {
-   16|      1|    let is_true = std::env::args().len() == 1;
-   17|      1|    let mut generator = || {
-   18|      1|        yield get_u32(is_true);
-   19|      1|        return "foo";
-   20|      1|    };
-   21|       |
-   22|      1|    match Pin::new(&mut generator).resume(()) {
-   23|      1|        GeneratorState::Yielded(Ok(1)) => {}
-   24|      0|        _ => panic!("unexpected return from resume"),
-   25|       |    }
-   26|      1|    match Pin::new(&mut generator).resume(()) {
-   27|      1|        GeneratorState::Complete("foo") => {}
-   28|      0|        _ => panic!("unexpected return from resume"),
-   29|       |    }
-   30|      1|}
+   LL|      1|}
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    let is_true = std::env::args().len() == 1;
+   LL|      1|    let mut generator = || {
+   LL|      1|        yield get_u32(is_true);
+   LL|      1|        return "foo";
+   LL|      1|    };
+   LL|       |
+   LL|      1|    match Pin::new(&mut generator).resume(()) {
+   LL|      1|        GeneratorState::Yielded(Ok(1)) => {}
+   LL|      0|        _ => panic!("unexpected return from resume"),
+   LL|       |    }
+   LL|      1|    match Pin::new(&mut generator).resume(()) {
+   LL|      1|        GeneratorState::Complete("foo") => {}
+   LL|      0|        _ => panic!("unexpected return from resume"),
+   LL|       |    }
+   LL|      1|}
 
diff --git a/tests/run-coverage/generics.coverage b/tests/run-coverage/generics.coverage
index 7a7649674ca..2ff8f917ed7 100644
--- a/tests/run-coverage/generics.coverage
+++ b/tests/run-coverage/generics.coverage
@@ -1,71 +1,71 @@
-    1|       |#![allow(unused_assignments)]
-    2|       |// failure-status: 1
-    3|       |
-    4|       |struct Firework<T> where T: Copy + std::fmt::Display {
-    5|       |    strength: T,
-    6|       |}
-    7|       |
-    8|       |impl<T> Firework<T> where T: Copy + std::fmt::Display {
-    9|       |    #[inline(always)]
-   10|      3|    fn set_strength(&mut self, new_strength: T) {
-   11|      3|        self.strength = new_strength;
-   12|      3|    }
+   LL|       |#![allow(unused_assignments)]
+   LL|       |// failure-status: 1
+   LL|       |
+   LL|       |struct Firework<T> where T: Copy + std::fmt::Display {
+   LL|       |    strength: T,
+   LL|       |}
+   LL|       |
+   LL|       |impl<T> Firework<T> where T: Copy + std::fmt::Display {
+   LL|       |    #[inline(always)]
+   LL|      3|    fn set_strength(&mut self, new_strength: T) {
+   LL|      3|        self.strength = new_strength;
+   LL|      3|    }
   ------------------
   | <generics::Firework<f64>>::set_strength:
-  |   10|      2|    fn set_strength(&mut self, new_strength: T) {
-  |   11|      2|        self.strength = new_strength;
-  |   12|      2|    }
+  |   LL|      2|    fn set_strength(&mut self, new_strength: T) {
+  |   LL|      2|        self.strength = new_strength;
+  |   LL|      2|    }
   ------------------
   | <generics::Firework<i32>>::set_strength:
-  |   10|      1|    fn set_strength(&mut self, new_strength: T) {
-  |   11|      1|        self.strength = new_strength;
-  |   12|      1|    }
+  |   LL|      1|    fn set_strength(&mut self, new_strength: T) {
+  |   LL|      1|        self.strength = new_strength;
+  |   LL|      1|    }
   ------------------
-   13|       |}
-   14|       |
-   15|       |impl<T> Drop for Firework<T> where T: Copy + std::fmt::Display {
-   16|       |    #[inline(always)]
-   17|      2|    fn drop(&mut self) {
-   18|      2|        println!("BOOM times {}!!!", self.strength);
-   19|      2|    }
+   LL|       |}
+   LL|       |
+   LL|       |impl<T> Drop for Firework<T> where T: Copy + std::fmt::Display {
+   LL|       |    #[inline(always)]
+   LL|      2|    fn drop(&mut self) {
+   LL|      2|        println!("BOOM times {}!!!", self.strength);
+   LL|      2|    }
   ------------------
   | <generics::Firework<f64> as core::ops::drop::Drop>::drop:
-  |   17|      1|    fn drop(&mut self) {
-  |   18|      1|        println!("BOOM times {}!!!", self.strength);
-  |   19|      1|    }
+  |   LL|      1|    fn drop(&mut self) {
+  |   LL|      1|        println!("BOOM times {}!!!", self.strength);
+  |   LL|      1|    }
   ------------------
   | <generics::Firework<i32> as core::ops::drop::Drop>::drop:
-  |   17|      1|    fn drop(&mut self) {
-  |   18|      1|        println!("BOOM times {}!!!", self.strength);
-  |   19|      1|    }
+  |   LL|      1|    fn drop(&mut self) {
+  |   LL|      1|        println!("BOOM times {}!!!", self.strength);
+  |   LL|      1|    }
   ------------------
-   20|       |}
-   21|       |
-   22|      1|fn main() -> Result<(),u8> {
-   23|      1|    let mut firecracker = Firework { strength: 1 };
-   24|      1|    firecracker.set_strength(2);
-   25|      1|
-   26|      1|    let mut tnt = Firework { strength: 100.1 };
-   27|      1|    tnt.set_strength(200.1);
-   28|      1|    tnt.set_strength(300.3);
-   29|      1|
-   30|      1|    if true {
-   31|      1|        println!("Exiting with error...");
-   32|      1|        return Err(1);
-   33|      0|    }
-   34|      0|
-   35|      0|
-   36|      0|
-   37|      0|
-   38|      0|
-   39|      0|    let _ = Firework { strength: 1000 };
-   40|      0|
-   41|      0|    Ok(())
-   42|      1|}
-   43|       |
-   44|       |// Expected program output:
-   45|       |//   Exiting with error...
-   46|       |//   BOOM times 100!!!
-   47|       |//   BOOM times 1!!!
-   48|       |//   Error: 1
+   LL|       |}
+   LL|       |
+   LL|      1|fn main() -> Result<(),u8> {
+   LL|      1|    let mut firecracker = Firework { strength: 1 };
+   LL|      1|    firecracker.set_strength(2);
+   LL|      1|
+   LL|      1|    let mut tnt = Firework { strength: 100.1 };
+   LL|      1|    tnt.set_strength(200.1);
+   LL|      1|    tnt.set_strength(300.3);
+   LL|      1|
+   LL|      1|    if true {
+   LL|      1|        println!("Exiting with error...");
+   LL|      1|        return Err(1);
+   LL|      0|    }
+   LL|      0|
+   LL|      0|
+   LL|      0|
+   LL|      0|
+   LL|      0|
+   LL|      0|    let _ = Firework { strength: 1000 };
+   LL|      0|
+   LL|      0|    Ok(())
+   LL|      1|}
+   LL|       |
+   LL|       |// Expected program output:
+   LL|       |//   Exiting with error...
+   LL|       |//   BOOM times 100!!!
+   LL|       |//   BOOM times 1!!!
+   LL|       |//   Error: 1
 
diff --git a/tests/run-coverage/if.coverage b/tests/run-coverage/if.coverage
index 0c9eff227ed..2e6845190aa 100644
--- a/tests/run-coverage/if.coverage
+++ b/tests/run-coverage/if.coverage
@@ -1,30 +1,30 @@
-    1|       |#![allow(unused_assignments, unused_variables)]
-    2|       |
-    3|      1|fn main() {
-    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    6|      1|    // dependent conditions.
-    7|      1|    let
-    8|      1|    is_true
-    9|      1|    =
-   10|      1|        std::env::args().len()
-   11|      1|    ==
-   12|      1|        1
-   13|      1|    ;
-   14|      1|    let
-   15|      1|        mut
-   16|      1|    countdown
-   17|      1|    =
-   18|      1|        0
-   19|      1|    ;
-   20|      1|    if
-   21|      1|        is_true
-   22|      1|    {
-   23|      1|        countdown
-   24|      1|        =
-   25|      1|            10
-   26|      1|        ;
-   27|      1|    }
+   LL|       |#![allow(unused_assignments, unused_variables)]
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+   LL|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   LL|      1|    // dependent conditions.
+   LL|      1|    let
+   LL|      1|    is_true
+   LL|      1|    =
+   LL|      1|        std::env::args().len()
+   LL|      1|    ==
+   LL|      1|        1
+   LL|      1|    ;
+   LL|      1|    let
+   LL|      1|        mut
+   LL|      1|    countdown
+   LL|      1|    =
+   LL|      1|        0
+   LL|      1|    ;
+   LL|      1|    if
+   LL|      1|        is_true
+   LL|      1|    {
+   LL|      1|        countdown
+   LL|      1|        =
+   LL|      1|            10
+   LL|      1|        ;
+   LL|      1|    }
                    ^0
-   28|      1|}
+   LL|      1|}
 
diff --git a/tests/run-coverage/if_else.coverage b/tests/run-coverage/if_else.coverage
index 4285d318686..0274401f004 100644
--- a/tests/run-coverage/if_else.coverage
+++ b/tests/run-coverage/if_else.coverage
@@ -1,41 +1,41 @@
-    1|       |#![allow(unused_assignments, unused_variables)]
-    2|       |
-    3|      1|fn main() {
-    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    6|      1|    // dependent conditions.
-    7|      1|    let is_true = std::env::args().len() == 1;
-    8|      1|
-    9|      1|    let mut countdown = 0;
-   10|      1|    if
-   11|      1|        is_true
-   12|      1|    {
-   13|      1|        countdown
-   14|      1|        =
-   15|      1|            10
-   16|      1|        ;
-   17|      1|    }
-   18|       |    else // Note coverage region difference without semicolon
-   19|       |    {
-   20|      0|        countdown
-   21|      0|        =
-   22|      0|            100
-   23|       |    }
-   24|       |
-   25|       |    if
-   26|      1|        is_true
-   27|      1|    {
-   28|      1|        countdown
-   29|      1|        =
-   30|      1|            10
-   31|      1|        ;
-   32|      1|    }
-   33|       |    else
-   34|      0|    {
-   35|      0|        countdown
-   36|      0|        =
-   37|      0|            100
-   38|      0|        ;
-   39|      0|    }
-   40|      1|}
+   LL|       |#![allow(unused_assignments, unused_variables)]
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+   LL|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   LL|      1|    // dependent conditions.
+   LL|      1|    let is_true = std::env::args().len() == 1;
+   LL|      1|
+   LL|      1|    let mut countdown = 0;
+   LL|      1|    if
+   LL|      1|        is_true
+   LL|      1|    {
+   LL|      1|        countdown
+   LL|      1|        =
+   LL|      1|            10
+   LL|      1|        ;
+   LL|      1|    }
+   LL|       |    else // Note coverage region difference without semicolon
+   LL|       |    {
+   LL|      0|        countdown
+   LL|      0|        =
+   LL|      0|            100
+   LL|       |    }
+   LL|       |
+   LL|       |    if
+   LL|      1|        is_true
+   LL|      1|    {
+   LL|      1|        countdown
+   LL|      1|        =
+   LL|      1|            10
+   LL|      1|        ;
+   LL|      1|    }
+   LL|       |    else
+   LL|      0|    {
+   LL|      0|        countdown
+   LL|      0|        =
+   LL|      0|            100
+   LL|      0|        ;
+   LL|      0|    }
+   LL|      1|}
 
diff --git a/tests/run-coverage/inline-dead.coverage b/tests/run-coverage/inline-dead.coverage
index a59fe1146f4..de96aa17acd 100644
--- a/tests/run-coverage/inline-dead.coverage
+++ b/tests/run-coverage/inline-dead.coverage
@@ -1,28 +1,28 @@
-    1|       |// Regression test for issue #98833.
-    2|       |// compile-flags: -Zinline-mir -Cdebug-assertions=off
-    3|       |
-    4|      1|fn main() {
-    5|      1|    println!("{}", live::<false>());
-    6|      1|
-    7|      1|    let f = |x: bool| {
-    8|       |        debug_assert!(
-    9|      0|            x
-   10|       |        );
-   11|      1|    };
-   12|      1|    f(false);
-   13|      1|}
-   14|       |
-   15|       |#[inline]
-   16|      1|fn live<const B: bool>() -> u32 {
-   17|      1|    if B {
-   18|      0|        dead()
-   19|       |    } else {
-   20|      1|        0
-   21|       |    }
-   22|      1|}
-   23|       |
-   24|       |#[inline]
-   25|      0|fn dead() -> u32 {
-   26|      0|    42
-   27|      0|}
+   LL|       |// Regression test for issue #98833.
+   LL|       |// compile-flags: -Zinline-mir -Cdebug-assertions=off
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    println!("{}", live::<false>());
+   LL|      1|
+   LL|      1|    let f = |x: bool| {
+   LL|       |        debug_assert!(
+   LL|      0|            x
+   LL|       |        );
+   LL|      1|    };
+   LL|      1|    f(false);
+   LL|      1|}
+   LL|       |
+   LL|       |#[inline]
+   LL|      1|fn live<const B: bool>() -> u32 {
+   LL|      1|    if B {
+   LL|      0|        dead()
+   LL|       |    } else {
+   LL|      1|        0
+   LL|       |    }
+   LL|      1|}
+   LL|       |
+   LL|       |#[inline]
+   LL|      0|fn dead() -> u32 {
+   LL|      0|    42
+   LL|      0|}
 
diff --git a/tests/run-coverage/inline.coverage b/tests/run-coverage/inline.coverage
index 6f5d1544fa0..6efd9a0830b 100644
--- a/tests/run-coverage/inline.coverage
+++ b/tests/run-coverage/inline.coverage
@@ -1,54 +1,54 @@
-    1|       |// compile-flags: -Zinline-mir
-    2|       |
-    3|       |use std::fmt::Display;
-    4|       |
-    5|      1|fn main() {
-    6|      1|    permutations(&['a', 'b', 'c']);
-    7|      1|}
-    8|       |
-    9|       |#[inline(always)]
-   10|      1|fn permutations<T: Copy + Display>(xs: &[T]) {
-   11|      1|    let mut ys = xs.to_owned();
-   12|      1|    permutate(&mut ys, 0);
-   13|      1|}
-   14|       |
-   15|     16|fn permutate<T: Copy + Display>(xs: &mut [T], k: usize) {
-   16|     16|    let n = length(xs);
-   17|     16|    if k == n {
-   18|      6|        display(xs);
-   19|     10|    } else if k < n {
-   20|     15|        for i in k..n {
+   LL|       |// compile-flags: -Zinline-mir
+   LL|       |
+   LL|       |use std::fmt::Display;
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    permutations(&['a', 'b', 'c']);
+   LL|      1|}
+   LL|       |
+   LL|       |#[inline(always)]
+   LL|      1|fn permutations<T: Copy + Display>(xs: &[T]) {
+   LL|      1|    let mut ys = xs.to_owned();
+   LL|      1|    permutate(&mut ys, 0);
+   LL|      1|}
+   LL|       |
+   LL|     16|fn permutate<T: Copy + Display>(xs: &mut [T], k: usize) {
+   LL|     16|    let n = length(xs);
+   LL|     16|    if k == n {
+   LL|      6|        display(xs);
+   LL|     10|    } else if k < n {
+   LL|     15|        for i in k..n {
                                ^10
-   21|     15|            swap(xs, i, k);
-   22|     15|            permutate(xs, k + 1);
-   23|     15|            swap(xs, i, k);
-   24|     15|        }
-   25|      0|    } else {
-   26|      0|        error();
-   27|      0|    }
-   28|     16|}
-   29|       |
-   30|     16|fn length<T>(xs: &[T]) -> usize {
-   31|     16|    xs.len()
-   32|     16|}
-   33|       |
-   34|       |#[inline]
-   35|     30|fn swap<T: Copy>(xs: &mut [T], i: usize, j: usize) {
-   36|     30|    let t = xs[i];
-   37|     30|    xs[i] = xs[j];
-   38|     30|    xs[j] = t;
-   39|     30|}
-   40|       |
-   41|      6|fn display<T: Display>(xs: &[T]) {
-   42|     24|    for x in xs {
+   LL|     15|            swap(xs, i, k);
+   LL|     15|            permutate(xs, k + 1);
+   LL|     15|            swap(xs, i, k);
+   LL|     15|        }
+   LL|      0|    } else {
+   LL|      0|        error();
+   LL|      0|    }
+   LL|     16|}
+   LL|       |
+   LL|     16|fn length<T>(xs: &[T]) -> usize {
+   LL|     16|    xs.len()
+   LL|     16|}
+   LL|       |
+   LL|       |#[inline]
+   LL|     30|fn swap<T: Copy>(xs: &mut [T], i: usize, j: usize) {
+   LL|     30|    let t = xs[i];
+   LL|     30|    xs[i] = xs[j];
+   LL|     30|    xs[j] = t;
+   LL|     30|}
+   LL|       |
+   LL|      6|fn display<T: Display>(xs: &[T]) {
+   LL|     24|    for x in xs {
                       ^18
-   43|     18|        print!("{}", x);
-   44|     18|    }
-   45|      6|    println!();
-   46|      6|}
-   47|       |
-   48|       |#[inline(always)]
-   49|      0|fn error() {
-   50|      0|    panic!("error");
-   51|      0|}
+   LL|     18|        print!("{}", x);
+   LL|     18|    }
+   LL|      6|    println!();
+   LL|      6|}
+   LL|       |
+   LL|       |#[inline(always)]
+   LL|      0|fn error() {
+   LL|      0|    panic!("error");
+   LL|      0|}
 
diff --git a/tests/run-coverage/inner_items.coverage b/tests/run-coverage/inner_items.coverage
index 883254a09ba..65493bcd9db 100644
--- a/tests/run-coverage/inner_items.coverage
+++ b/tests/run-coverage/inner_items.coverage
@@ -1,60 +1,60 @@
-    1|       |#![allow(unused_assignments, unused_variables, dead_code)]
-    2|       |
-    3|      1|fn main() {
-    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    6|      1|    // dependent conditions.
-    7|      1|    let is_true = std::env::args().len() == 1;
-    8|      1|
-    9|      1|    let mut countdown = 0;
-   10|      1|    if is_true {
-   11|      1|        countdown = 10;
-   12|      1|    }
+   LL|       |#![allow(unused_assignments, unused_variables, dead_code)]
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+   LL|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   LL|      1|    // dependent conditions.
+   LL|      1|    let is_true = std::env::args().len() == 1;
+   LL|      1|
+   LL|      1|    let mut countdown = 0;
+   LL|      1|    if is_true {
+   LL|      1|        countdown = 10;
+   LL|      1|    }
                    ^0
-   13|       |
-   14|       |    mod in_mod {
-   15|       |        const IN_MOD_CONST: u32 = 1000;
-   16|       |    }
-   17|       |
-   18|      3|    fn in_func(a: u32) {
-   19|      3|        let b = 1;
-   20|      3|        let c = a + b;
-   21|      3|        println!("c = {}", c)
-   22|      3|    }
-   23|       |
-   24|       |    struct InStruct {
-   25|       |        in_struct_field: u32,
-   26|       |    }
-   27|       |
-   28|       |    const IN_CONST: u32 = 1234;
-   29|       |
-   30|       |    trait InTrait {
-   31|       |        fn trait_func(&mut self, incr: u32);
-   32|       |
-   33|      1|        fn default_trait_func(&mut self) {
-   34|      1|            in_func(IN_CONST);
-   35|      1|            self.trait_func(IN_CONST);
-   36|      1|        }
-   37|       |    }
-   38|       |
-   39|       |    impl InTrait for InStruct {
-   40|      1|        fn trait_func(&mut self, incr: u32) {
-   41|      1|            self.in_struct_field += incr;
-   42|      1|            in_func(self.in_struct_field);
-   43|      1|        }
-   44|       |    }
-   45|       |
-   46|       |    type InType = String;
-   47|       |
-   48|      1|    if is_true {
-   49|      1|        in_func(countdown);
-   50|      1|    }
+   LL|       |
+   LL|       |    mod in_mod {
+   LL|       |        const IN_MOD_CONST: u32 = 1000;
+   LL|       |    }
+   LL|       |
+   LL|      3|    fn in_func(a: u32) {
+   LL|      3|        let b = 1;
+   LL|      3|        let c = a + b;
+   LL|      3|        println!("c = {}", c)
+   LL|      3|    }
+   LL|       |
+   LL|       |    struct InStruct {
+   LL|       |        in_struct_field: u32,
+   LL|       |    }
+   LL|       |
+   LL|       |    const IN_CONST: u32 = 1234;
+   LL|       |
+   LL|       |    trait InTrait {
+   LL|       |        fn trait_func(&mut self, incr: u32);
+   LL|       |
+   LL|      1|        fn default_trait_func(&mut self) {
+   LL|      1|            in_func(IN_CONST);
+   LL|      1|            self.trait_func(IN_CONST);
+   LL|      1|        }
+   LL|       |    }
+   LL|       |
+   LL|       |    impl InTrait for InStruct {
+   LL|      1|        fn trait_func(&mut self, incr: u32) {
+   LL|      1|            self.in_struct_field += incr;
+   LL|      1|            in_func(self.in_struct_field);
+   LL|      1|        }
+   LL|       |    }
+   LL|       |
+   LL|       |    type InType = String;
+   LL|       |
+   LL|      1|    if is_true {
+   LL|      1|        in_func(countdown);
+   LL|      1|    }
                    ^0
-   51|       |
-   52|      1|    let mut val = InStruct {
-   53|      1|        in_struct_field: 101,
-   54|      1|    };
-   55|      1|
-   56|      1|    val.default_trait_func();
-   57|      1|}
+   LL|       |
+   LL|      1|    let mut val = InStruct {
+   LL|      1|        in_struct_field: 101,
+   LL|      1|    };
+   LL|      1|
+   LL|      1|    val.default_trait_func();
+   LL|      1|}
 
diff --git a/tests/run-coverage/issue-83601.coverage b/tests/run-coverage/issue-83601.coverage
index 25c74ab2e70..7995332cad3 100644
--- a/tests/run-coverage/issue-83601.coverage
+++ b/tests/run-coverage/issue-83601.coverage
@@ -1,16 +1,16 @@
-    1|       |// Shows that rust-lang/rust/83601 is resolved
-    2|       |
-    3|      3|#[derive(Debug, PartialEq, Eq)]
+   LL|       |// Shows that rust-lang/rust/83601 is resolved
+   LL|       |
+   LL|      3|#[derive(Debug, PartialEq, Eq)]
                               ^2
-    4|       |struct Foo(u32);
-    5|       |
-    6|      1|fn main() {
-    7|      1|    let bar = Foo(1);
-    8|      1|    assert_eq!(bar, Foo(1));
-    9|      1|    let baz = Foo(0);
-   10|      1|    assert_ne!(baz, Foo(1));
-   11|      1|    println!("{:?}", Foo(1));
-   12|      1|    println!("{:?}", bar);
-   13|      1|    println!("{:?}", baz);
-   14|      1|}
+   LL|       |struct Foo(u32);
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    let bar = Foo(1);
+   LL|      1|    assert_eq!(bar, Foo(1));
+   LL|      1|    let baz = Foo(0);
+   LL|      1|    assert_ne!(baz, Foo(1));
+   LL|      1|    println!("{:?}", Foo(1));
+   LL|      1|    println!("{:?}", bar);
+   LL|      1|    println!("{:?}", baz);
+   LL|      1|}
 
diff --git a/tests/run-coverage/issue-84561.coverage b/tests/run-coverage/issue-84561.coverage
index 7a97e353245..222f877d36a 100644
--- a/tests/run-coverage/issue-84561.coverage
+++ b/tests/run-coverage/issue-84561.coverage
@@ -1,189 +1,189 @@
-    1|       |// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
-    2|       |
-    3|       |// failure-status: 101
-    4|     21|#[derive(PartialEq, Eq)]
-    5|       |struct Foo(u32);
-    6|      1|fn test3() {
-    7|      1|    let is_true = std::env::args().len() == 1;
-    8|      1|    let bar = Foo(1);
-    9|      1|    assert_eq!(bar, Foo(1));
-   10|      1|    let baz = Foo(0);
-   11|      1|    assert_ne!(baz, Foo(1));
-   12|      1|    println!("{:?}", Foo(1));
-   13|      1|    println!("{:?}", bar);
-   14|      1|    println!("{:?}", baz);
-   15|      1|
-   16|      1|    assert_eq!(Foo(1), Foo(1));
-   17|      1|    assert_ne!(Foo(0), Foo(1));
-   18|      1|    assert_eq!(Foo(2), Foo(2));
-   19|      1|    let bar = Foo(0);
-   20|      1|    assert_ne!(bar, Foo(3));
-   21|      1|    assert_ne!(Foo(0), Foo(4));
-   22|      1|    assert_eq!(Foo(3), Foo(3), "with a message");
+   LL|       |// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results.
+   LL|       |
+   LL|       |// failure-status: 101
+   LL|     21|#[derive(PartialEq, Eq)]
+   LL|       |struct Foo(u32);
+   LL|      1|fn test3() {
+   LL|      1|    let is_true = std::env::args().len() == 1;
+   LL|      1|    let bar = Foo(1);
+   LL|      1|    assert_eq!(bar, Foo(1));
+   LL|      1|    let baz = Foo(0);
+   LL|      1|    assert_ne!(baz, Foo(1));
+   LL|      1|    println!("{:?}", Foo(1));
+   LL|      1|    println!("{:?}", bar);
+   LL|      1|    println!("{:?}", baz);
+   LL|      1|
+   LL|      1|    assert_eq!(Foo(1), Foo(1));
+   LL|      1|    assert_ne!(Foo(0), Foo(1));
+   LL|      1|    assert_eq!(Foo(2), Foo(2));
+   LL|      1|    let bar = Foo(0);
+   LL|      1|    assert_ne!(bar, Foo(3));
+   LL|      1|    assert_ne!(Foo(0), Foo(4));
+   LL|      1|    assert_eq!(Foo(3), Foo(3), "with a message");
                                              ^0
-   23|      1|    println!("{:?}", bar);
-   24|      1|    println!("{:?}", Foo(1));
-   25|      1|
-   26|      1|    assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" });
+   LL|      1|    println!("{:?}", bar);
+   LL|      1|    println!("{:?}", Foo(1));
+   LL|      1|
+   LL|      1|    assert_ne!(Foo(0), Foo(5), "{}", if is_true { "true message" } else { "false message" });
                                              ^0                 ^0                      ^0
-   27|      1|    assert_ne!(
-   28|       |        Foo(0)
-   29|       |        ,
-   30|       |        Foo(5)
-   31|       |        ,
-   32|      0|        "{}"
-   33|      0|        ,
-   34|      0|        if
-   35|      0|        is_true
-   36|       |        {
-   37|      0|            "true message"
-   38|       |        } else {
-   39|      0|            "false message"
-   40|       |        }
-   41|       |    );
-   42|       |
-   43|      1|    let is_true = std::env::args().len() == 1;
-   44|      1|
-   45|      1|    assert_eq!(
-   46|      1|        Foo(1),
-   47|      1|        Foo(1)
-   48|      1|    );
-   49|      1|    assert_ne!(
-   50|      1|        Foo(0),
-   51|      1|        Foo(1)
-   52|      1|    );
-   53|      1|    assert_eq!(
-   54|      1|        Foo(2),
-   55|      1|        Foo(2)
-   56|      1|    );
-   57|      1|    let bar = Foo(1);
-   58|      1|    assert_ne!(
-   59|      1|        bar,
-   60|      1|        Foo(3)
-   61|      1|    );
-   62|      1|    if is_true {
-   63|      1|        assert_ne!(
-   64|      1|            Foo(0),
-   65|      1|            Foo(4)
-   66|      1|        );
-   67|       |    } else {
-   68|      0|        assert_eq!(
-   69|      0|            Foo(3),
-   70|      0|            Foo(3)
-   71|      0|        );
-   72|       |    }
-   73|      1|    if is_true {
-   74|      1|        assert_ne!(
-   75|       |            Foo(0),
-   76|       |            Foo(4),
-   77|      0|            "with a message"
-   78|       |        );
-   79|       |    } else {
-   80|      0|        assert_eq!(
-   81|       |            Foo(3),
-   82|       |            Foo(3),
-   83|      0|            "with a message"
-   84|       |        );
-   85|       |    }
-   86|      1|    assert_ne!(
-   87|      1|        if is_true {
-   88|      1|            Foo(0)
-   89|       |        } else {
-   90|      0|            Foo(1)
-   91|       |        },
-   92|       |        Foo(5)
-   93|       |    );
-   94|      1|    assert_ne!(
-   95|      1|        Foo(5),
-   96|      1|        if is_true {
-   97|      1|            Foo(0)
-   98|       |        } else {
-   99|      0|            Foo(1)
-  100|       |        }
-  101|       |    );
-  102|      1|    assert_ne!(
-  103|      1|        if is_true {
-  104|      1|            assert_eq!(
-  105|      1|                Foo(3),
-  106|      1|                Foo(3)
-  107|      1|            );
-  108|      1|            Foo(0)
-  109|       |        } else {
-  110|      0|            assert_ne!(
-  111|      0|                if is_true {
-  112|      0|                    Foo(0)
-  113|       |                } else {
-  114|      0|                    Foo(1)
-  115|       |                },
-  116|       |                Foo(5)
-  117|       |            );
-  118|      0|            Foo(1)
-  119|       |        },
-  120|       |        Foo(5),
-  121|      0|        "with a message"
-  122|       |    );
-  123|      1|    assert_eq!(
-  124|       |        Foo(1),
-  125|       |        Foo(3),
-  126|      1|        "this assert should fail"
-  127|       |    );
-  128|      0|    assert_eq!(
-  129|       |        Foo(3),
-  130|       |        Foo(3),
-  131|      0|        "this assert should not be reached"
-  132|       |    );
-  133|      0|}
-  134|       |
-  135|       |impl std::fmt::Debug for Foo {
-  136|       |    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-  137|      7|        write!(f, "try and succeed")?;
+   LL|      1|    assert_ne!(
+   LL|       |        Foo(0)
+   LL|       |        ,
+   LL|       |        Foo(5)
+   LL|       |        ,
+   LL|      0|        "{}"
+   LL|      0|        ,
+   LL|      0|        if
+   LL|      0|        is_true
+   LL|       |        {
+   LL|      0|            "true message"
+   LL|       |        } else {
+   LL|      0|            "false message"
+   LL|       |        }
+   LL|       |    );
+   LL|       |
+   LL|      1|    let is_true = std::env::args().len() == 1;
+   LL|      1|
+   LL|      1|    assert_eq!(
+   LL|      1|        Foo(1),
+   LL|      1|        Foo(1)
+   LL|      1|    );
+   LL|      1|    assert_ne!(
+   LL|      1|        Foo(0),
+   LL|      1|        Foo(1)
+   LL|      1|    );
+   LL|      1|    assert_eq!(
+   LL|      1|        Foo(2),
+   LL|      1|        Foo(2)
+   LL|      1|    );
+   LL|      1|    let bar = Foo(1);
+   LL|      1|    assert_ne!(
+   LL|      1|        bar,
+   LL|      1|        Foo(3)
+   LL|      1|    );
+   LL|      1|    if is_true {
+   LL|      1|        assert_ne!(
+   LL|      1|            Foo(0),
+   LL|      1|            Foo(4)
+   LL|      1|        );
+   LL|       |    } else {
+   LL|      0|        assert_eq!(
+   LL|      0|            Foo(3),
+   LL|      0|            Foo(3)
+   LL|      0|        );
+   LL|       |    }
+   LL|      1|    if is_true {
+   LL|      1|        assert_ne!(
+   LL|       |            Foo(0),
+   LL|       |            Foo(4),
+   LL|      0|            "with a message"
+   LL|       |        );
+   LL|       |    } else {
+   LL|      0|        assert_eq!(
+   LL|       |            Foo(3),
+   LL|       |            Foo(3),
+   LL|      0|            "with a message"
+   LL|       |        );
+   LL|       |    }
+   LL|      1|    assert_ne!(
+   LL|      1|        if is_true {
+   LL|      1|            Foo(0)
+   LL|       |        } else {
+   LL|      0|            Foo(1)
+   LL|       |        },
+   LL|       |        Foo(5)
+   LL|       |    );
+   LL|      1|    assert_ne!(
+   LL|      1|        Foo(5),
+   LL|      1|        if is_true {
+   LL|      1|            Foo(0)
+   LL|       |        } else {
+   LL|      0|            Foo(1)
+   LL|       |        }
+   LL|       |    );
+   LL|      1|    assert_ne!(
+   LL|      1|        if is_true {
+   LL|      1|            assert_eq!(
+   LL|      1|                Foo(3),
+   LL|      1|                Foo(3)
+   LL|      1|            );
+   LL|      1|            Foo(0)
+   LL|       |        } else {
+   LL|      0|            assert_ne!(
+   LL|      0|                if is_true {
+   LL|      0|                    Foo(0)
+   LL|       |                } else {
+   LL|      0|                    Foo(1)
+   LL|       |                },
+   LL|       |                Foo(5)
+   LL|       |            );
+   LL|      0|            Foo(1)
+   LL|       |        },
+   LL|       |        Foo(5),
+   LL|      0|        "with a message"
+   LL|       |    );
+   LL|      1|    assert_eq!(
+   LL|       |        Foo(1),
+   LL|       |        Foo(3),
+   LL|      1|        "this assert should fail"
+   LL|       |    );
+   LL|      0|    assert_eq!(
+   LL|       |        Foo(3),
+   LL|       |        Foo(3),
+   LL|      0|        "this assert should not be reached"
+   LL|       |    );
+   LL|      0|}
+   LL|       |
+   LL|       |impl std::fmt::Debug for Foo {
+   LL|       |    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+   LL|      7|        write!(f, "try and succeed")?;
                                                   ^0
-  138|      7|        Ok(())
-  139|      7|    }
-  140|       |}
-  141|       |
-  142|       |static mut DEBUG_LEVEL_ENABLED: bool = false;
-  143|       |
-  144|       |macro_rules! debug {
-  145|       |    ($($arg:tt)+) => (
-  146|       |        if unsafe { DEBUG_LEVEL_ENABLED } {
-  147|       |            println!($($arg)+);
-  148|       |        }
-  149|       |    );
-  150|       |}
-  151|       |
-  152|      1|fn test1() {
-  153|      1|    debug!("debug is enabled");
+   LL|      7|        Ok(())
+   LL|      7|    }
+   LL|       |}
+   LL|       |
+   LL|       |static mut DEBUG_LEVEL_ENABLED: bool = false;
+   LL|       |
+   LL|       |macro_rules! debug {
+   LL|       |    ($($arg:tt)+) => (
+   LL|       |        if unsafe { DEBUG_LEVEL_ENABLED } {
+   LL|       |            println!($($arg)+);
+   LL|       |        }
+   LL|       |    );
+   LL|       |}
+   LL|       |
+   LL|      1|fn test1() {
+   LL|      1|    debug!("debug is enabled");
                          ^0
-  154|      1|    debug!("debug is enabled");
+   LL|      1|    debug!("debug is enabled");
                          ^0
-  155|      1|    let _ = 0;
-  156|      1|    debug!("debug is enabled");
+   LL|      1|    let _ = 0;
+   LL|      1|    debug!("debug is enabled");
                          ^0
-  157|      1|    unsafe {
-  158|      1|        DEBUG_LEVEL_ENABLED = true;
-  159|      1|    }
-  160|      1|    debug!("debug is enabled");
-  161|      1|}
-  162|       |
-  163|       |macro_rules! call_debug {
-  164|       |    ($($arg:tt)+) => (
-  165|      1|        fn call_print(s: &str) {
-  166|      1|            print!("{}", s);
-  167|      1|        }
-  168|       |
-  169|       |        call_print("called from call_debug: ");
-  170|       |        debug!($($arg)+);
-  171|       |    );
-  172|       |}
-  173|       |
-  174|      1|fn test2() {
-  175|      1|    call_debug!("debug is enabled");
-  176|      1|}
-  177|       |
-  178|      1|fn main() {
-  179|      1|    test1();
-  180|      1|    test2();
-  181|      1|    test3();
-  182|      1|}
+   LL|      1|    unsafe {
+   LL|      1|        DEBUG_LEVEL_ENABLED = true;
+   LL|      1|    }
+   LL|      1|    debug!("debug is enabled");
+   LL|      1|}
+   LL|       |
+   LL|       |macro_rules! call_debug {
+   LL|       |    ($($arg:tt)+) => (
+   LL|      1|        fn call_print(s: &str) {
+   LL|      1|            print!("{}", s);
+   LL|      1|        }
+   LL|       |
+   LL|       |        call_print("called from call_debug: ");
+   LL|       |        debug!($($arg)+);
+   LL|       |    );
+   LL|       |}
+   LL|       |
+   LL|      1|fn test2() {
+   LL|      1|    call_debug!("debug is enabled");
+   LL|      1|}
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    test1();
+   LL|      1|    test2();
+   LL|      1|    test3();
+   LL|      1|}
 
diff --git a/tests/run-coverage/issue-85461.coverage b/tests/run-coverage/issue-85461.coverage
index d78a4a1129c..f97ab230387 100644
--- a/tests/run-coverage/issue-85461.coverage
+++ b/tests/run-coverage/issue-85461.coverage
@@ -1,36 +1,36 @@
 $DIR/auxiliary/inline_always_with_dead_code.rs:
-    1|       |// compile-flags: -Cinstrument-coverage -Ccodegen-units=4 -Copt-level=0
-    2|       |
-    3|       |#![allow(dead_code)]
-    4|       |
-    5|       |mod foo {
-    6|       |    #[inline(always)]
-    7|      2|    pub fn called() { }
-    8|       |
-    9|      0|    fn uncalled() { }
-   10|       |}
-   11|       |
-   12|       |pub mod bar {
-   13|      1|    pub fn call_me() {
-   14|      1|        super::foo::called();
-   15|      1|    }
-   16|       |}
-   17|       |
-   18|       |pub mod baz {
-   19|      1|    pub fn call_me() {
-   20|      1|        super::foo::called();
-   21|      1|    }
-   22|       |}
+   LL|       |// compile-flags: -Cinstrument-coverage -Ccodegen-units=4 -Copt-level=0
+   LL|       |
+   LL|       |#![allow(dead_code)]
+   LL|       |
+   LL|       |mod foo {
+   LL|       |    #[inline(always)]
+   LL|      2|    pub fn called() { }
+   LL|       |
+   LL|      0|    fn uncalled() { }
+   LL|       |}
+   LL|       |
+   LL|       |pub mod bar {
+   LL|      1|    pub fn call_me() {
+   LL|      1|        super::foo::called();
+   LL|      1|    }
+   LL|       |}
+   LL|       |
+   LL|       |pub mod baz {
+   LL|      1|    pub fn call_me() {
+   LL|      1|        super::foo::called();
+   LL|      1|    }
+   LL|       |}
 
 $DIR/issue-85461.rs:
-    1|       |// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]
-    2|       |// aux-build:inline_always_with_dead_code.rs
-    3|       |extern crate inline_always_with_dead_code;
-    4|       |
-    5|       |use inline_always_with_dead_code::{bar, baz};
-    6|       |
-    7|      1|fn main() {
-    8|      1|    bar::call_me();
-    9|      1|    baz::call_me();
-   10|      1|}
+   LL|       |// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)]
+   LL|       |// aux-build:inline_always_with_dead_code.rs
+   LL|       |extern crate inline_always_with_dead_code;
+   LL|       |
+   LL|       |use inline_always_with_dead_code::{bar, baz};
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    bar::call_me();
+   LL|      1|    baz::call_me();
+   LL|      1|}
 
diff --git a/tests/run-coverage/issue-93054.coverage b/tests/run-coverage/issue-93054.coverage
index a1655adedd4..074e6b9835a 100644
--- a/tests/run-coverage/issue-93054.coverage
+++ b/tests/run-coverage/issue-93054.coverage
@@ -1,29 +1,29 @@
-    1|       |// Regression test for #93054: Functions using uninhabited types often only have a single,
-    2|       |// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail.
-    3|       |// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them.
-    4|       |
-    5|       |// compile-flags: --edition=2021
-    6|       |
-    7|       |enum Never { }
-    8|       |
-    9|       |impl Never {
-   10|       |    fn foo(self) {
-   11|       |        match self { }
-   12|       |        make().map(|never| match never { });
-   13|       |    }
-   14|       |
-   15|       |    fn bar(&self) {
-   16|       |        match *self { }
-   17|       |    }
-   18|       |}
-   19|       |
-   20|      0|async fn foo2(never: Never) {
-   21|       |    match never { }
-   22|       |}
-   23|       |
-   24|      0|fn make() -> Option<Never> {
-   25|      0|    None
-   26|      0|}
-   27|       |
-   28|      1|fn main() { }
+   LL|       |// Regression test for #93054: Functions using uninhabited types often only have a single,
+   LL|       |// unreachable basic block which doesn't get instrumented. This should not cause llvm-cov to fail.
+   LL|       |// Since these kinds functions can't be invoked anyway, it's ok to not have coverage data for them.
+   LL|       |
+   LL|       |// compile-flags: --edition=2021
+   LL|       |
+   LL|       |enum Never { }
+   LL|       |
+   LL|       |impl Never {
+   LL|       |    fn foo(self) {
+   LL|       |        match self { }
+   LL|       |        make().map(|never| match never { });
+   LL|       |    }
+   LL|       |
+   LL|       |    fn bar(&self) {
+   LL|       |        match *self { }
+   LL|       |    }
+   LL|       |}
+   LL|       |
+   LL|      0|async fn foo2(never: Never) {
+   LL|       |    match never { }
+   LL|       |}
+   LL|       |
+   LL|      0|fn make() -> Option<Never> {
+   LL|      0|    None
+   LL|      0|}
+   LL|       |
+   LL|      1|fn main() { }
 
diff --git a/tests/run-coverage/lazy_boolean.coverage b/tests/run-coverage/lazy_boolean.coverage
index bd349df2fbc..2d927a08356 100644
--- a/tests/run-coverage/lazy_boolean.coverage
+++ b/tests/run-coverage/lazy_boolean.coverage
@@ -1,64 +1,64 @@
-    1|       |#![allow(unused_assignments, unused_variables)]
-    2|       |
-    3|      1|fn main() {
-    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    6|      1|    // dependent conditions.
-    7|      1|    let is_true = std::env::args().len() == 1;
-    8|      1|
-    9|      1|    let (mut a, mut b, mut c) = (0, 0, 0);
-   10|      1|    if is_true {
-   11|      1|        a = 1;
-   12|      1|        b = 10;
-   13|      1|        c = 100;
-   14|      1|    }
+   LL|       |#![allow(unused_assignments, unused_variables)]
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+   LL|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   LL|      1|    // dependent conditions.
+   LL|      1|    let is_true = std::env::args().len() == 1;
+   LL|      1|
+   LL|      1|    let (mut a, mut b, mut c) = (0, 0, 0);
+   LL|      1|    if is_true {
+   LL|      1|        a = 1;
+   LL|      1|        b = 10;
+   LL|      1|        c = 100;
+   LL|      1|    }
                    ^0
-   15|       |    let
-   16|      1|        somebool
-   17|       |        =
-   18|      1|            a < b
-   19|       |        ||
-   20|      0|            b < c
-   21|       |    ;
-   22|       |    let
-   23|      1|        somebool
-   24|       |        =
-   25|      1|            b < a
-   26|       |        ||
-   27|      1|            b < c
-   28|       |    ;
-   29|      1|    let somebool = a < b && b < c;
-   30|      1|    let somebool = b < a && b < c;
+   LL|       |    let
+   LL|      1|        somebool
+   LL|       |        =
+   LL|      1|            a < b
+   LL|       |        ||
+   LL|      0|            b < c
+   LL|       |    ;
+   LL|       |    let
+   LL|      1|        somebool
+   LL|       |        =
+   LL|      1|            b < a
+   LL|       |        ||
+   LL|      1|            b < c
+   LL|       |    ;
+   LL|      1|    let somebool = a < b && b < c;
+   LL|      1|    let somebool = b < a && b < c;
                                           ^0
-   31|       |
-   32|       |    if
-   33|      1|        !
-   34|      1|        is_true
-   35|      0|    {
-   36|      0|        a = 2
-   37|      0|        ;
-   38|      1|    }
-   39|       |
-   40|       |    if
-   41|      1|        is_true
-   42|      1|    {
-   43|      1|        b = 30
-   44|      1|        ;
-   45|      1|    }
-   46|       |    else
-   47|      0|    {
-   48|      0|        c = 400
-   49|      0|        ;
-   50|      0|    }
-   51|       |
-   52|      1|    if !is_true {
-   53|      0|        a = 2;
-   54|      1|    }
-   55|       |
-   56|      1|    if is_true {
-   57|      1|        b = 30;
-   58|      1|    } else {
-   59|      0|        c = 400;
-   60|      0|    }
-   61|      1|}
+   LL|       |
+   LL|       |    if
+   LL|      1|        !
+   LL|      1|        is_true
+   LL|      0|    {
+   LL|      0|        a = 2
+   LL|      0|        ;
+   LL|      1|    }
+   LL|       |
+   LL|       |    if
+   LL|      1|        is_true
+   LL|      1|    {
+   LL|      1|        b = 30
+   LL|      1|        ;
+   LL|      1|    }
+   LL|       |    else
+   LL|      0|    {
+   LL|      0|        c = 400
+   LL|      0|        ;
+   LL|      0|    }
+   LL|       |
+   LL|      1|    if !is_true {
+   LL|      0|        a = 2;
+   LL|      1|    }
+   LL|       |
+   LL|      1|    if is_true {
+   LL|      1|        b = 30;
+   LL|      1|    } else {
+   LL|      0|        c = 400;
+   LL|      0|    }
+   LL|      1|}
 
diff --git a/tests/run-coverage/loop_break_value.coverage b/tests/run-coverage/loop_break_value.coverage
index 022fe4c5962..1f0630636dd 100644
--- a/tests/run-coverage/loop_break_value.coverage
+++ b/tests/run-coverage/loop_break_value.coverage
@@ -1,14 +1,14 @@
-    1|       |#![allow(unused_assignments, unused_variables)]
-    2|       |
-    3|      1|fn main() {
-    4|      1|    let result
-    5|      1|        =
-    6|      1|            loop
-    7|      1|        {
-    8|      1|            break
-    9|      1|            10
-   10|      1|            ;
-   11|      1|        }
-   12|      1|    ;
-   13|      1|}
+   LL|       |#![allow(unused_assignments, unused_variables)]
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    let result
+   LL|      1|        =
+   LL|      1|            loop
+   LL|      1|        {
+   LL|      1|            break
+   LL|      1|            10
+   LL|      1|            ;
+   LL|      1|        }
+   LL|      1|    ;
+   LL|      1|}
 
diff --git a/tests/run-coverage/loops_branches.coverage b/tests/run-coverage/loops_branches.coverage
index b7ad79a2484..148a22377f3 100644
--- a/tests/run-coverage/loops_branches.coverage
+++ b/tests/run-coverage/loops_branches.coverage
@@ -1,68 +1,68 @@
-    1|       |#![allow(unused_assignments, unused_variables, while_true)]
-    2|       |
-    3|       |// This test confirms that (1) unexecuted infinite loops are handled correctly by the
-    4|       |// InstrumentCoverage MIR pass; and (2) Counter Expressions that subtract from zero can be dropped.
-    5|       |
-    6|       |struct DebugTest;
-    7|       |
-    8|       |impl std::fmt::Debug for DebugTest {
-    9|      1|    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-   10|      1|        if true {
-   11|      1|            if false {
-   12|      0|                while true {
-   13|      0|                }
-   14|      1|            }
-   15|      1|            write!(f, "cool")?;
+   LL|       |#![allow(unused_assignments, unused_variables, while_true)]
+   LL|       |
+   LL|       |// This test confirms that (1) unexecuted infinite loops are handled correctly by the
+   LL|       |// InstrumentCoverage MIR pass; and (2) Counter Expressions that subtract from zero can be dropped.
+   LL|       |
+   LL|       |struct DebugTest;
+   LL|       |
+   LL|       |impl std::fmt::Debug for DebugTest {
+   LL|      1|    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+   LL|      1|        if true {
+   LL|      1|            if false {
+   LL|      0|                while true {
+   LL|      0|                }
+   LL|      1|            }
+   LL|      1|            write!(f, "cool")?;
                                            ^0
-   16|      0|        } else {
-   17|      0|        }
-   18|       |
-   19|     11|        for i in 0..10 {
+   LL|      0|        } else {
+   LL|      0|        }
+   LL|       |
+   LL|     11|        for i in 0..10 {
                           ^10
-   20|     10|            if true {
-   21|     10|                if false {
-   22|      0|                    while true {}
-   23|     10|                }
-   24|     10|                write!(f, "cool")?;
+   LL|     10|            if true {
+   LL|     10|                if false {
+   LL|      0|                    while true {}
+   LL|     10|                }
+   LL|     10|                write!(f, "cool")?;
                                                ^0
-   25|      0|            } else {
-   26|      0|            }
-   27|       |        }
-   28|      1|        Ok(())
-   29|      1|    }
-   30|       |}
-   31|       |
-   32|       |struct DisplayTest;
-   33|       |
-   34|       |impl std::fmt::Display for DisplayTest {
-   35|      1|    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-   36|      1|        if false {
-   37|      0|        } else {
-   38|      1|            if false {
-   39|      0|                while true {}
-   40|      1|            }
-   41|      1|            write!(f, "cool")?;
+   LL|      0|            } else {
+   LL|      0|            }
+   LL|       |        }
+   LL|      1|        Ok(())
+   LL|      1|    }
+   LL|       |}
+   LL|       |
+   LL|       |struct DisplayTest;
+   LL|       |
+   LL|       |impl std::fmt::Display for DisplayTest {
+   LL|      1|    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+   LL|      1|        if false {
+   LL|      0|        } else {
+   LL|      1|            if false {
+   LL|      0|                while true {}
+   LL|      1|            }
+   LL|      1|            write!(f, "cool")?;
                                            ^0
-   42|       |        }
-   43|     11|        for i in 0..10 {
+   LL|       |        }
+   LL|     11|        for i in 0..10 {
                           ^10
-   44|     10|            if false {
-   45|      0|            } else {
-   46|     10|                if false {
-   47|      0|                    while true {}
-   48|     10|                }
-   49|     10|                write!(f, "cool")?;
+   LL|     10|            if false {
+   LL|      0|            } else {
+   LL|     10|                if false {
+   LL|      0|                    while true {}
+   LL|     10|                }
+   LL|     10|                write!(f, "cool")?;
                                                ^0
-   50|       |            }
-   51|       |        }
-   52|      1|        Ok(())
-   53|      1|    }
-   54|       |}
-   55|       |
-   56|      1|fn main() {
-   57|      1|    let debug_test = DebugTest;
-   58|      1|    println!("{:?}", debug_test);
-   59|      1|    let display_test = DisplayTest;
-   60|      1|    println!("{}", display_test);
-   61|      1|}
+   LL|       |            }
+   LL|       |        }
+   LL|      1|        Ok(())
+   LL|      1|    }
+   LL|       |}
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    let debug_test = DebugTest;
+   LL|      1|    println!("{:?}", debug_test);
+   LL|      1|    let display_test = DisplayTest;
+   LL|      1|    println!("{}", display_test);
+   LL|      1|}
 
diff --git a/tests/run-coverage/match_or_pattern.coverage b/tests/run-coverage/match_or_pattern.coverage
index a0fccb24f99..0b5a2c03dd3 100644
--- a/tests/run-coverage/match_or_pattern.coverage
+++ b/tests/run-coverage/match_or_pattern.coverage
@@ -1,50 +1,50 @@
-    1|       |#![feature(or_patterns)]
-    2|       |
-    3|      1|fn main() {
-    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    6|      1|    // dependent conditions.
-    7|      1|    let is_true = std::env::args().len() == 1;
-    8|      1|
-    9|      1|    let mut a: u8 = 0;
-   10|      1|    let mut b: u8 = 0;
-   11|      1|    if is_true {
-   12|      1|        a = 2;
-   13|      1|        b = 0;
-   14|      1|    }
+   LL|       |#![feature(or_patterns)]
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+   LL|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   LL|      1|    // dependent conditions.
+   LL|      1|    let is_true = std::env::args().len() == 1;
+   LL|      1|
+   LL|      1|    let mut a: u8 = 0;
+   LL|      1|    let mut b: u8 = 0;
+   LL|      1|    if is_true {
+   LL|      1|        a = 2;
+   LL|      1|        b = 0;
+   LL|      1|    }
                    ^0
-   15|      1|    match (a, b) {
-   16|       |        // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`.
-   17|       |        // This test confirms a fix for Issue #79569.
-   18|      0|        (0 | 1, 2 | 3) => {}
-   19|      1|        _ => {}
-   20|       |    }
-   21|      1|    if is_true {
-   22|      1|        a = 0;
-   23|      1|        b = 0;
-   24|      1|    }
+   LL|      1|    match (a, b) {
+   LL|       |        // Or patterns generate MIR `SwitchInt` with multiple targets to the same `BasicBlock`.
+   LL|       |        // This test confirms a fix for Issue #79569.
+   LL|      0|        (0 | 1, 2 | 3) => {}
+   LL|      1|        _ => {}
+   LL|       |    }
+   LL|      1|    if is_true {
+   LL|      1|        a = 0;
+   LL|      1|        b = 0;
+   LL|      1|    }
                    ^0
-   25|      1|    match (a, b) {
-   26|      0|        (0 | 1, 2 | 3) => {}
-   27|      1|        _ => {}
-   28|       |    }
-   29|      1|    if is_true {
-   30|      1|        a = 2;
-   31|      1|        b = 2;
-   32|      1|    }
+   LL|      1|    match (a, b) {
+   LL|      0|        (0 | 1, 2 | 3) => {}
+   LL|      1|        _ => {}
+   LL|       |    }
+   LL|      1|    if is_true {
+   LL|      1|        a = 2;
+   LL|      1|        b = 2;
+   LL|      1|    }
                    ^0
-   33|      1|    match (a, b) {
-   34|      0|        (0 | 1, 2 | 3) => {}
-   35|      1|        _ => {}
-   36|       |    }
-   37|      1|    if is_true {
-   38|      1|        a = 0;
-   39|      1|        b = 2;
-   40|      1|    }
+   LL|      1|    match (a, b) {
+   LL|      0|        (0 | 1, 2 | 3) => {}
+   LL|      1|        _ => {}
+   LL|       |    }
+   LL|      1|    if is_true {
+   LL|      1|        a = 0;
+   LL|      1|        b = 2;
+   LL|      1|    }
                    ^0
-   41|      1|    match (a, b) {
-   42|      1|        (0 | 1, 2 | 3) => {}
-   43|      0|        _ => {}
-   44|       |    }
-   45|      1|}
+   LL|      1|    match (a, b) {
+   LL|      1|        (0 | 1, 2 | 3) => {}
+   LL|      0|        _ => {}
+   LL|       |    }
+   LL|      1|}
 
diff --git a/tests/run-coverage/nested_loops.coverage b/tests/run-coverage/nested_loops.coverage
index 0dbd6bcf313..143d0d26aa7 100644
--- a/tests/run-coverage/nested_loops.coverage
+++ b/tests/run-coverage/nested_loops.coverage
@@ -1,26 +1,26 @@
-    1|      1|fn main() {
-    2|      1|    let is_true = std::env::args().len() == 1;
-    3|      1|    let mut countdown = 10;
-    4|       |
-    5|      1|    'outer: while countdown > 0 {
-    6|      1|        let mut a = 100;
-    7|      1|        let mut b = 100;
-    8|      3|        for _ in 0..50 {
-    9|      3|            if a < 30 {
-   10|      0|                break;
-   11|      3|            }
-   12|      3|            a -= 5;
-   13|      3|            b -= 5;
-   14|      3|            if b < 90 {
-   15|      1|                a -= 10;
-   16|      1|                if is_true {
-   17|      1|                    break 'outer;
-   18|      0|                } else {
-   19|      0|                    a -= 2;
-   20|      0|                }
-   21|      2|            }
-   22|       |        }
-   23|      0|        countdown -= 1;
-   24|       |    }
-   25|      1|}
+   LL|      1|fn main() {
+   LL|      1|    let is_true = std::env::args().len() == 1;
+   LL|      1|    let mut countdown = 10;
+   LL|       |
+   LL|      1|    'outer: while countdown > 0 {
+   LL|      1|        let mut a = 100;
+   LL|      1|        let mut b = 100;
+   LL|      3|        for _ in 0..50 {
+   LL|      3|            if a < 30 {
+   LL|      0|                break;
+   LL|      3|            }
+   LL|      3|            a -= 5;
+   LL|      3|            b -= 5;
+   LL|      3|            if b < 90 {
+   LL|      1|                a -= 10;
+   LL|      1|                if is_true {
+   LL|      1|                    break 'outer;
+   LL|      0|                } else {
+   LL|      0|                    a -= 2;
+   LL|      0|                }
+   LL|      2|            }
+   LL|       |        }
+   LL|      0|        countdown -= 1;
+   LL|       |    }
+   LL|      1|}
 
diff --git a/tests/run-coverage/no_cov_crate.coverage b/tests/run-coverage/no_cov_crate.coverage
index 83a9204136f..c34dbde888a 100644
--- a/tests/run-coverage/no_cov_crate.coverage
+++ b/tests/run-coverage/no_cov_crate.coverage
@@ -1,87 +1,87 @@
-    1|       |// Enables `no_coverage` on the entire crate
-    2|       |#![feature(no_coverage)]
-    3|       |
-    4|       |#[no_coverage]
-    5|       |fn do_not_add_coverage_1() {
-    6|       |    println!("called but not covered");
-    7|       |}
-    8|       |
-    9|       |fn do_not_add_coverage_2() {
-   10|       |    #![no_coverage]
-   11|       |    println!("called but not covered");
-   12|       |}
-   13|       |
-   14|       |#[no_coverage]
-   15|       |fn do_not_add_coverage_not_called() {
-   16|       |    println!("not called and not covered");
-   17|       |}
-   18|       |
-   19|      1|fn add_coverage_1() {
-   20|      1|    println!("called and covered");
-   21|      1|}
-   22|       |
-   23|      1|fn add_coverage_2() {
-   24|      1|    println!("called and covered");
-   25|      1|}
-   26|       |
-   27|      0|fn add_coverage_not_called() {
-   28|      0|    println!("not called but covered");
-   29|      0|}
-   30|       |
-   31|       |// FIXME: These test-cases illustrate confusing results of nested functions.
-   32|       |// See https://github.com/rust-lang/rust/issues/93319
-   33|       |mod nested_fns {
-   34|       |    #[no_coverage]
-   35|       |    pub fn outer_not_covered(is_true: bool) {
-   36|      1|        fn inner(is_true: bool) {
-   37|      1|            if is_true {
-   38|      1|                println!("called and covered");
-   39|      1|            } else {
-   40|      0|                println!("absolutely not covered");
-   41|      0|            }
-   42|      1|        }
-   43|       |        println!("called but not covered");
-   44|       |        inner(is_true);
-   45|       |    }
-   46|       |
-   47|      1|    pub fn outer(is_true: bool) {
-   48|      1|        println!("called and covered");
-   49|      1|        inner_not_covered(is_true);
-   50|      1|
-   51|      1|        #[no_coverage]
-   52|      1|        fn inner_not_covered(is_true: bool) {
-   53|      1|            if is_true {
-   54|      1|                println!("called but not covered");
-   55|      1|            } else {
-   56|      1|                println!("absolutely not covered");
-   57|      1|            }
-   58|      1|        }
-   59|      1|    }
-   60|       |
-   61|      1|    pub fn outer_both_covered(is_true: bool) {
-   62|      1|        println!("called and covered");
-   63|      1|        inner(is_true);
-   64|      1|
-   65|      1|        fn inner(is_true: bool) {
-   66|      1|            if is_true {
-   67|      1|                println!("called and covered");
-   68|      1|            } else {
-   69|      0|                println!("absolutely not covered");
-   70|      0|            }
-   71|      1|        }
-   72|      1|    }
-   73|       |}
-   74|       |
-   75|      1|fn main() {
-   76|      1|    let is_true = std::env::args().len() == 1;
-   77|      1|
-   78|      1|    do_not_add_coverage_1();
-   79|      1|    do_not_add_coverage_2();
-   80|      1|    add_coverage_1();
-   81|      1|    add_coverage_2();
-   82|      1|
-   83|      1|    nested_fns::outer_not_covered(is_true);
-   84|      1|    nested_fns::outer(is_true);
-   85|      1|    nested_fns::outer_both_covered(is_true);
-   86|      1|}
+   LL|       |// Enables `no_coverage` on the entire crate
+   LL|       |#![feature(no_coverage)]
+   LL|       |
+   LL|       |#[no_coverage]
+   LL|       |fn do_not_add_coverage_1() {
+   LL|       |    println!("called but not covered");
+   LL|       |}
+   LL|       |
+   LL|       |fn do_not_add_coverage_2() {
+   LL|       |    #![no_coverage]
+   LL|       |    println!("called but not covered");
+   LL|       |}
+   LL|       |
+   LL|       |#[no_coverage]
+   LL|       |fn do_not_add_coverage_not_called() {
+   LL|       |    println!("not called and not covered");
+   LL|       |}
+   LL|       |
+   LL|      1|fn add_coverage_1() {
+   LL|      1|    println!("called and covered");
+   LL|      1|}
+   LL|       |
+   LL|      1|fn add_coverage_2() {
+   LL|      1|    println!("called and covered");
+   LL|      1|}
+   LL|       |
+   LL|      0|fn add_coverage_not_called() {
+   LL|      0|    println!("not called but covered");
+   LL|      0|}
+   LL|       |
+   LL|       |// FIXME: These test-cases illustrate confusing results of nested functions.
+   LL|       |// See https://github.com/rust-lang/rust/issues/93319
+   LL|       |mod nested_fns {
+   LL|       |    #[no_coverage]
+   LL|       |    pub fn outer_not_covered(is_true: bool) {
+   LL|      1|        fn inner(is_true: bool) {
+   LL|      1|            if is_true {
+   LL|      1|                println!("called and covered");
+   LL|      1|            } else {
+   LL|      0|                println!("absolutely not covered");
+   LL|      0|            }
+   LL|      1|        }
+   LL|       |        println!("called but not covered");
+   LL|       |        inner(is_true);
+   LL|       |    }
+   LL|       |
+   LL|      1|    pub fn outer(is_true: bool) {
+   LL|      1|        println!("called and covered");
+   LL|      1|        inner_not_covered(is_true);
+   LL|      1|
+   LL|      1|        #[no_coverage]
+   LL|      1|        fn inner_not_covered(is_true: bool) {
+   LL|      1|            if is_true {
+   LL|      1|                println!("called but not covered");
+   LL|      1|            } else {
+   LL|      1|                println!("absolutely not covered");
+   LL|      1|            }
+   LL|      1|        }
+   LL|      1|    }
+   LL|       |
+   LL|      1|    pub fn outer_both_covered(is_true: bool) {
+   LL|      1|        println!("called and covered");
+   LL|      1|        inner(is_true);
+   LL|      1|
+   LL|      1|        fn inner(is_true: bool) {
+   LL|      1|            if is_true {
+   LL|      1|                println!("called and covered");
+   LL|      1|            } else {
+   LL|      0|                println!("absolutely not covered");
+   LL|      0|            }
+   LL|      1|        }
+   LL|      1|    }
+   LL|       |}
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    let is_true = std::env::args().len() == 1;
+   LL|      1|
+   LL|      1|    do_not_add_coverage_1();
+   LL|      1|    do_not_add_coverage_2();
+   LL|      1|    add_coverage_1();
+   LL|      1|    add_coverage_2();
+   LL|      1|
+   LL|      1|    nested_fns::outer_not_covered(is_true);
+   LL|      1|    nested_fns::outer(is_true);
+   LL|      1|    nested_fns::outer_both_covered(is_true);
+   LL|      1|}
 
diff --git a/tests/run-coverage/overflow.coverage b/tests/run-coverage/overflow.coverage
index 95043759166..2d60316e215 100644
--- a/tests/run-coverage/overflow.coverage
+++ b/tests/run-coverage/overflow.coverage
@@ -1,64 +1,64 @@
-    1|       |#![allow(unused_assignments)]
-    2|       |// failure-status: 101
-    3|       |
-    4|      4|fn might_overflow(to_add: u32) -> u32 {
-    5|      4|    if to_add > 5 {
-    6|      1|        println!("this will probably overflow");
-    7|      3|    }
-    8|      4|    let add_to = u32::MAX - 5;
-    9|      4|    println!("does {} + {} overflow?", add_to, to_add);
-   10|      4|    let result = to_add + add_to;
-   11|      4|    println!("continuing after overflow check");
-   12|      4|    result
-   13|      4|}
-   14|       |
-   15|      1|fn main() -> Result<(),u8> {
-   16|      1|    let mut countdown = 10;
-   17|     11|    while countdown > 0 {
-   18|     11|        if countdown == 1 {
-   19|      1|            let result = might_overflow(10);
-   20|      1|            println!("Result: {}", result);
-   21|     10|        } else if countdown < 5 {
-   22|      3|            let result = might_overflow(1);
-   23|      3|            println!("Result: {}", result);
-   24|      6|        }
-   25|     10|        countdown -= 1;
-   26|       |    }
-   27|      0|    Ok(())
-   28|      0|}
-   29|       |
-   30|       |// Notes:
-   31|       |//   1. Compare this program and its coverage results to those of the very similar test `assert.rs`,
-   32|       |//      and similar tests `panic_unwind.rs`, abort.rs` and `try_error_result.rs`.
-   33|       |//   2. This test confirms the coverage generated when a program passes or fails a
-   34|       |//      compiler-generated `TerminatorKind::Assert` (based on an overflow check, in this case).
-   35|       |//   3. Similar to how the coverage instrumentation handles `TerminatorKind::Call`,
-   36|       |//      compiler-generated assertion failures are assumed to be a symptom of a program bug, not
-   37|       |//      expected behavior. To simplify the coverage graphs and keep instrumented programs as
-   38|       |//      small and fast as possible, `Assert` terminators are assumed to always succeed, and
-   39|       |//      therefore are considered "non-branching" terminators. So, an `Assert` terminator does not
-   40|       |//      get its own coverage counter.
-   41|       |//   4. After an unhandled panic or failed Assert, coverage results may not always be intuitive.
-   42|       |//      In this test, the final count for the statements after the `if` block in `might_overflow()`
-   43|       |//      is 4, even though the lines after `to_add + add_to` were executed only 3 times. Depending
-   44|       |//      on the MIR graph and the structure of the code, this count could have been 3 (which might
-   45|       |//      have been valid for the overflowed add `+`, but should have been 4 for the lines before
-   46|       |//      the overflow. The reason for this potential uncertainty is, a `CounterKind` is incremented
-   47|       |//      via StatementKind::Counter at the end of the block, but (as in the case in this test),
-   48|       |//      a CounterKind::Expression is always evaluated. In this case, the expression was based on
-   49|       |//      a `Counter` incremented as part of the evaluation of the `if` expression, which was
-   50|       |//      executed, and counted, 4 times, before reaching the overflow add.
-   51|       |
-   52|       |// If the program did not overflow, the coverage for `might_overflow()` would look like this:
-   53|       |//
-   54|       |//     4|       |fn might_overflow(to_add: u32) -> u32 {
-   55|       |//     5|      4|    if to_add > 5 {
-   56|       |//     6|      0|        println!("this will probably overflow");
-   57|       |//     7|      4|    }
-   58|       |//     8|      4|    let add_to = u32::MAX - 5;
-   59|       |//     9|      4|    println!("does {} + {} overflow?", add_to, to_add);
-   60|       |//    10|      4|    let result = to_add + add_to;
-   61|       |//    11|      4|    println!("continuing after overflow check");
-   62|       |//    12|      4|    result
-   63|       |//    13|      4|}
+   LL|       |#![allow(unused_assignments)]
+   LL|       |// failure-status: 101
+   LL|       |
+   LL|      4|fn might_overflow(to_add: u32) -> u32 {
+   LL|      4|    if to_add > 5 {
+   LL|      1|        println!("this will probably overflow");
+   LL|      3|    }
+   LL|      4|    let add_to = u32::MAX - 5;
+   LL|      4|    println!("does {} + {} overflow?", add_to, to_add);
+   LL|      4|    let result = to_add + add_to;
+   LL|      4|    println!("continuing after overflow check");
+   LL|      4|    result
+   LL|      4|}
+   LL|       |
+   LL|      1|fn main() -> Result<(),u8> {
+   LL|      1|    let mut countdown = 10;
+   LL|     11|    while countdown > 0 {
+   LL|     11|        if countdown == 1 {
+   LL|      1|            let result = might_overflow(10);
+   LL|      1|            println!("Result: {}", result);
+   LL|     10|        } else if countdown < 5 {
+   LL|      3|            let result = might_overflow(1);
+   LL|      3|            println!("Result: {}", result);
+   LL|      6|        }
+   LL|     10|        countdown -= 1;
+   LL|       |    }
+   LL|      0|    Ok(())
+   LL|      0|}
+   LL|       |
+   LL|       |// Notes:
+   LL|       |//   1. Compare this program and its coverage results to those of the very similar test `assert.rs`,
+   LL|       |//      and similar tests `panic_unwind.rs`, abort.rs` and `try_error_result.rs`.
+   LL|       |//   2. This test confirms the coverage generated when a program passes or fails a
+   LL|       |//      compiler-generated `TerminatorKind::Assert` (based on an overflow check, in this case).
+   LL|       |//   3. Similar to how the coverage instrumentation handles `TerminatorKind::Call`,
+   LL|       |//      compiler-generated assertion failures are assumed to be a symptom of a program bug, not
+   LL|       |//      expected behavior. To simplify the coverage graphs and keep instrumented programs as
+   LL|       |//      small and fast as possible, `Assert` terminators are assumed to always succeed, and
+   LL|       |//      therefore are considered "non-branching" terminators. So, an `Assert` terminator does not
+   LL|       |//      get its own coverage counter.
+   LL|       |//   4. After an unhandled panic or failed Assert, coverage results may not always be intuitive.
+   LL|       |//      In this test, the final count for the statements after the `if` block in `might_overflow()`
+   LL|       |//      is 4, even though the lines after `to_add + add_to` were executed only 3 times. Depending
+   LL|       |//      on the MIR graph and the structure of the code, this count could have been 3 (which might
+   LL|       |//      have been valid for the overflowed add `+`, but should have been 4 for the lines before
+   LL|       |//      the overflow. The reason for this potential uncertainty is, a `CounterKind` is incremented
+   LL|       |//      via StatementKind::Counter at the end of the block, but (as in the case in this test),
+   LL|       |//      a CounterKind::Expression is always evaluated. In this case, the expression was based on
+   LL|       |//      a `Counter` incremented as part of the evaluation of the `if` expression, which was
+   LL|       |//      executed, and counted, 4 times, before reaching the overflow add.
+   LL|       |
+   LL|       |// If the program did not overflow, the coverage for `might_overflow()` would look like this:
+   LL|       |//
+   LL|       |//     4|       |fn might_overflow(to_add: u32) -> u32 {
+   LL|       |//     5|      4|    if to_add > 5 {
+   LL|       |//     6|      0|        println!("this will probably overflow");
+   LL|       |//     7|      4|    }
+   LL|       |//     8|      4|    let add_to = u32::MAX - 5;
+   LL|       |//     9|      4|    println!("does {} + {} overflow?", add_to, to_add);
+   LL|       |//    10|      4|    let result = to_add + add_to;
+   LL|       |//    11|      4|    println!("continuing after overflow check");
+   LL|       |//    12|      4|    result
+   LL|       |//    13|      4|}
 
diff --git a/tests/run-coverage/panic_unwind.coverage b/tests/run-coverage/panic_unwind.coverage
index 58b9ba448ee..2b0777ef215 100644
--- a/tests/run-coverage/panic_unwind.coverage
+++ b/tests/run-coverage/panic_unwind.coverage
@@ -1,32 +1,32 @@
-    1|       |#![allow(unused_assignments)]
-    2|       |// failure-status: 101
-    3|       |
-    4|      4|fn might_panic(should_panic: bool) {
-    5|      4|    if should_panic {
-    6|      1|        println!("panicking...");
-    7|      1|        panic!("panics");
-    8|      3|    } else {
-    9|      3|        println!("Don't Panic");
-   10|      3|    }
-   11|      3|}
-   12|       |
-   13|      1|fn main() -> Result<(), u8> {
-   14|      1|    let mut countdown = 10;
-   15|     11|    while countdown > 0 {
-   16|     11|        if countdown == 1 {
-   17|      1|            might_panic(true);
-   18|     10|        } else if countdown < 5 {
-   19|      3|            might_panic(false);
-   20|      6|        }
-   21|     10|        countdown -= 1;
-   22|       |    }
-   23|      0|    Ok(())
-   24|      0|}
-   25|       |
-   26|       |// Notes:
-   27|       |//   1. Compare this program and its coverage results to those of the similar tests `abort.rs` and
-   28|       |//      `try_error_result.rs`.
-   29|       |//   2. Since the `panic_unwind.rs` test is allowed to unwind, it is also allowed to execute the
-   30|       |//      normal program exit cleanup, including writing out the current values of the coverage
-   31|       |//      counters.
+   LL|       |#![allow(unused_assignments)]
+   LL|       |// failure-status: 101
+   LL|       |
+   LL|      4|fn might_panic(should_panic: bool) {
+   LL|      4|    if should_panic {
+   LL|      1|        println!("panicking...");
+   LL|      1|        panic!("panics");
+   LL|      3|    } else {
+   LL|      3|        println!("Don't Panic");
+   LL|      3|    }
+   LL|      3|}
+   LL|       |
+   LL|      1|fn main() -> Result<(), u8> {
+   LL|      1|    let mut countdown = 10;
+   LL|     11|    while countdown > 0 {
+   LL|     11|        if countdown == 1 {
+   LL|      1|            might_panic(true);
+   LL|     10|        } else if countdown < 5 {
+   LL|      3|            might_panic(false);
+   LL|      6|        }
+   LL|     10|        countdown -= 1;
+   LL|       |    }
+   LL|      0|    Ok(())
+   LL|      0|}
+   LL|       |
+   LL|       |// Notes:
+   LL|       |//   1. Compare this program and its coverage results to those of the similar tests `abort.rs` and
+   LL|       |//      `try_error_result.rs`.
+   LL|       |//   2. Since the `panic_unwind.rs` test is allowed to unwind, it is also allowed to execute the
+   LL|       |//      normal program exit cleanup, including writing out the current values of the coverage
+   LL|       |//      counters.
 
diff --git a/tests/run-coverage/partial_eq.coverage b/tests/run-coverage/partial_eq.coverage
index be4f23ec0ba..c6d9ad6cf27 100644
--- a/tests/run-coverage/partial_eq.coverage
+++ b/tests/run-coverage/partial_eq.coverage
@@ -1,48 +1,48 @@
-    1|       |// This test confirms an earlier problem was resolved, supporting the MIR graph generated by the
-    2|       |// structure of this test.
-    3|       |
-    4|      2|#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
+   LL|       |// This test confirms an earlier problem was resolved, supporting the MIR graph generated by the
+   LL|       |// structure of this test.
+   LL|       |
+   LL|      2|#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
                        ^0            ^0      ^0     ^1       ^1 ^0^0
-    5|       |pub struct Version {
-    6|       |    major: usize,
-    7|       |    minor: usize,
-    8|       |    patch: usize,
-    9|       |}
-   10|       |
-   11|       |impl Version {
-   12|      2|    pub fn new(major: usize, minor: usize, patch: usize) -> Self {
-   13|      2|        Self {
-   14|      2|            major,
-   15|      2|            minor,
-   16|      2|            patch,
-   17|      2|        }
-   18|      2|    }
-   19|       |}
-   20|       |
-   21|      1|fn main() {
-   22|      1|    let version_3_2_1 = Version::new(3, 2, 1);
-   23|      1|    let version_3_3_0 = Version::new(3, 3, 0);
-   24|      1|
-   25|      1|    println!("{:?} < {:?} = {}", version_3_2_1, version_3_3_0, version_3_2_1 < version_3_3_0);
-   26|      1|}
-   27|       |
-   28|       |/*
-   29|       |
-   30|       |This test verifies a bug was fixed that otherwise generated this error:
-   31|       |
-   32|       |thread 'rustc' panicked at 'No counters provided the source_hash for function:
-   33|       |    Instance {
-   34|       |        def: Item(WithOptConstParam {
-   35|       |            did: DefId(0:101 ~ autocfg[c44a]::version::{impl#2}::partial_cmp),
-   36|       |            const_param_did: None
-   37|       |        }),
-   38|       |        args: []
-   39|       |    }'
-   40|       |The `PartialOrd` derived by `Version` happened to generate a MIR that generated coverage
-   41|       |without a code region associated with any `Counter`. Code regions were associated with at least
-   42|       |one expression, which is allowed, but the `function_source_hash` was only passed to the codegen
-   43|       |(coverage mapgen) phase from a `Counter`s code region. A new method was added to pass the
-   44|       |`function_source_hash` without a code region, if necessary.
-   45|       |
-   46|       |*/
+   LL|       |pub struct Version {
+   LL|       |    major: usize,
+   LL|       |    minor: usize,
+   LL|       |    patch: usize,
+   LL|       |}
+   LL|       |
+   LL|       |impl Version {
+   LL|      2|    pub fn new(major: usize, minor: usize, patch: usize) -> Self {
+   LL|      2|        Self {
+   LL|      2|            major,
+   LL|      2|            minor,
+   LL|      2|            patch,
+   LL|      2|        }
+   LL|      2|    }
+   LL|       |}
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    let version_3_2_1 = Version::new(3, 2, 1);
+   LL|      1|    let version_3_3_0 = Version::new(3, 3, 0);
+   LL|      1|
+   LL|      1|    println!("{:?} < {:?} = {}", version_3_2_1, version_3_3_0, version_3_2_1 < version_3_3_0);
+   LL|      1|}
+   LL|       |
+   LL|       |/*
+   LL|       |
+   LL|       |This test verifies a bug was fixed that otherwise generated this error:
+   LL|       |
+   LL|       |thread 'rustc' panicked at 'No counters provided the source_hash for function:
+   LL|       |    Instance {
+   LL|       |        def: Item(WithOptConstParam {
+   LL|       |            did: DefId(0:101 ~ autocfg[c44a]::version::{impl#2}::partial_cmp),
+   LL|       |            const_param_did: None
+   LL|       |        }),
+   LL|       |        args: []
+   LL|       |    }'
+   LL|       |The `PartialOrd` derived by `Version` happened to generate a MIR that generated coverage
+   LL|       |without a code region associated with any `Counter`. Code regions were associated with at least
+   LL|       |one expression, which is allowed, but the `function_source_hash` was only passed to the codegen
+   LL|       |(coverage mapgen) phase from a `Counter`s code region. A new method was added to pass the
+   LL|       |`function_source_hash` without a code region, if necessary.
+   LL|       |
+   LL|       |*/
 
diff --git a/tests/run-coverage/simple_loop.coverage b/tests/run-coverage/simple_loop.coverage
index feb83bad674..691c6cd1e7d 100644
--- a/tests/run-coverage/simple_loop.coverage
+++ b/tests/run-coverage/simple_loop.coverage
@@ -1,37 +1,37 @@
-    1|       |#![allow(unused_assignments)]
-    2|       |
-    3|      1|fn main() {
-    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    6|      1|    // dependent conditions.
-    7|      1|    let is_true = std::env::args().len() == 1;
-    8|      1|
-    9|      1|    let mut countdown = 0;
-   10|      1|
-   11|      1|    if
-   12|      1|        is_true
-   13|      1|    {
-   14|      1|        countdown
-   15|      1|        =
-   16|      1|            10
-   17|      1|        ;
-   18|      1|    }
+   LL|       |#![allow(unused_assignments)]
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+   LL|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   LL|      1|    // dependent conditions.
+   LL|      1|    let is_true = std::env::args().len() == 1;
+   LL|      1|
+   LL|      1|    let mut countdown = 0;
+   LL|      1|
+   LL|      1|    if
+   LL|      1|        is_true
+   LL|      1|    {
+   LL|      1|        countdown
+   LL|      1|        =
+   LL|      1|            10
+   LL|      1|        ;
+   LL|      1|    }
                    ^0
-   19|       |
-   20|       |    loop
-   21|       |    {
-   22|       |        if
-   23|     11|            countdown
-   24|     11|                ==
-   25|     11|            0
-   26|       |        {
-   27|      1|            break
-   28|       |            ;
-   29|     10|        }
-   30|     10|        countdown
-   31|     10|        -=
-   32|     10|        1
-   33|       |        ;
-   34|       |    }
-   35|      1|}
+   LL|       |
+   LL|       |    loop
+   LL|       |    {
+   LL|       |        if
+   LL|     11|            countdown
+   LL|     11|                ==
+   LL|     11|            0
+   LL|       |        {
+   LL|      1|            break
+   LL|       |            ;
+   LL|     10|        }
+   LL|     10|        countdown
+   LL|     10|        -=
+   LL|     10|        1
+   LL|       |        ;
+   LL|       |    }
+   LL|      1|}
 
diff --git a/tests/run-coverage/simple_match.coverage b/tests/run-coverage/simple_match.coverage
index b9298213111..7f5dd3bb646 100644
--- a/tests/run-coverage/simple_match.coverage
+++ b/tests/run-coverage/simple_match.coverage
@@ -1,45 +1,45 @@
-    1|       |#![allow(unused_assignments, unused_variables)]
-    2|       |
-    3|      1|fn main() {
-    4|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    5|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    6|      1|    // dependent conditions.
-    7|      1|    let is_true = std::env::args().len() == 1;
-    8|      1|
-    9|      1|    let mut countdown = 1;
-   10|      1|    if is_true {
-   11|      1|        countdown = 0;
-   12|      1|    }
+   LL|       |#![allow(unused_assignments, unused_variables)]
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+   LL|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   LL|      1|    // dependent conditions.
+   LL|      1|    let is_true = std::env::args().len() == 1;
+   LL|      1|
+   LL|      1|    let mut countdown = 1;
+   LL|      1|    if is_true {
+   LL|      1|        countdown = 0;
+   LL|      1|    }
                    ^0
-   13|       |
-   14|       |    for
-   15|       |        _
-   16|       |    in
-   17|      3|        0..2
-   18|       |    {
-   19|       |        let z
-   20|       |        ;
-   21|       |        match
-   22|      2|            countdown
-   23|       |        {
-   24|      1|            x
-   25|       |            if
-   26|      2|                x
-   27|      2|                    <
-   28|      2|                1
-   29|       |            =>
-   30|      1|            {
-   31|      1|                z = countdown
-   32|      1|                ;
-   33|      1|                let y = countdown
-   34|      1|                ;
-   35|      1|                countdown = 10
-   36|      1|                ;
-   37|      1|            }
-   38|       |            _
-   39|       |            =>
-   40|      1|            {}
-   41|       |        }
-   42|       |    }
-   43|      1|}
+   LL|       |
+   LL|       |    for
+   LL|       |        _
+   LL|       |    in
+   LL|      3|        0..2
+   LL|       |    {
+   LL|       |        let z
+   LL|       |        ;
+   LL|       |        match
+   LL|      2|            countdown
+   LL|       |        {
+   LL|      1|            x
+   LL|       |            if
+   LL|      2|                x
+   LL|      2|                    <
+   LL|      2|                1
+   LL|       |            =>
+   LL|      1|            {
+   LL|      1|                z = countdown
+   LL|      1|                ;
+   LL|      1|                let y = countdown
+   LL|      1|                ;
+   LL|      1|                countdown = 10
+   LL|      1|                ;
+   LL|      1|            }
+   LL|       |            _
+   LL|       |            =>
+   LL|      1|            {}
+   LL|       |        }
+   LL|       |    }
+   LL|      1|}
 
diff --git a/tests/run-coverage/sort_groups.coverage b/tests/run-coverage/sort_groups.coverage
index 81468cb35da..8733bf48a9c 100644
--- a/tests/run-coverage/sort_groups.coverage
+++ b/tests/run-coverage/sort_groups.coverage
@@ -1,49 +1,49 @@
-    1|       |// compile-flags: --edition=2021
-    2|       |
-    3|       |// Demonstrate that `sort_subviews.py` can sort instantiation groups into a
-    4|       |// predictable order, while preserving their heterogeneous contents.
-    5|       |
-    6|      1|fn main() {
-    7|      1|    let cond = std::env::args().len() > 1;
-    8|      1|    generic_fn::<()>(cond);
-    9|      1|    generic_fn::<&'static str>(!cond);
-   10|      1|    if false {
-   11|      0|        generic_fn::<char>(cond);
-   12|      1|    }
-   13|      1|    generic_fn::<i32>(cond);
-   14|      1|    other_fn();
-   15|      1|}
-   16|       |
-   17|      3|fn generic_fn<T>(cond: bool) {
-   18|      3|    if cond {
-   19|      1|        println!("{}", std::any::type_name::<T>());
-   20|      2|    }
-   21|      3|}
+   LL|       |// compile-flags: --edition=2021
+   LL|       |
+   LL|       |// Demonstrate that `sort_subviews.py` can sort instantiation groups into a
+   LL|       |// predictable order, while preserving their heterogeneous contents.
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    let cond = std::env::args().len() > 1;
+   LL|      1|    generic_fn::<()>(cond);
+   LL|      1|    generic_fn::<&'static str>(!cond);
+   LL|      1|    if false {
+   LL|      0|        generic_fn::<char>(cond);
+   LL|      1|    }
+   LL|      1|    generic_fn::<i32>(cond);
+   LL|      1|    other_fn();
+   LL|      1|}
+   LL|       |
+   LL|      3|fn generic_fn<T>(cond: bool) {
+   LL|      3|    if cond {
+   LL|      1|        println!("{}", std::any::type_name::<T>());
+   LL|      2|    }
+   LL|      3|}
   ------------------
   | Unexecuted instantiation: sort_groups::generic_fn::<char>
   ------------------
   | sort_groups::generic_fn::<&str>:
-  |   17|      1|fn generic_fn<T>(cond: bool) {
-  |   18|      1|    if cond {
-  |   19|      1|        println!("{}", std::any::type_name::<T>());
-  |   20|      1|    }
+  |   LL|      1|fn generic_fn<T>(cond: bool) {
+  |   LL|      1|    if cond {
+  |   LL|      1|        println!("{}", std::any::type_name::<T>());
+  |   LL|      1|    }
   |                   ^0
-  |   21|      1|}
+  |   LL|      1|}
   ------------------
   | sort_groups::generic_fn::<()>:
-  |   17|      1|fn generic_fn<T>(cond: bool) {
-  |   18|      1|    if cond {
-  |   19|      0|        println!("{}", std::any::type_name::<T>());
-  |   20|      1|    }
-  |   21|      1|}
+  |   LL|      1|fn generic_fn<T>(cond: bool) {
+  |   LL|      1|    if cond {
+  |   LL|      0|        println!("{}", std::any::type_name::<T>());
+  |   LL|      1|    }
+  |   LL|      1|}
   ------------------
   | sort_groups::generic_fn::<i32>:
-  |   17|      1|fn generic_fn<T>(cond: bool) {
-  |   18|      1|    if cond {
-  |   19|      0|        println!("{}", std::any::type_name::<T>());
-  |   20|      1|    }
-  |   21|      1|}
+  |   LL|      1|fn generic_fn<T>(cond: bool) {
+  |   LL|      1|    if cond {
+  |   LL|      0|        println!("{}", std::any::type_name::<T>());
+  |   LL|      1|    }
+  |   LL|      1|}
   ------------------
-   22|       |
-   23|      1|fn other_fn() {}
+   LL|       |
+   LL|      1|fn other_fn() {}
 
diff --git a/tests/run-coverage/test_harness.coverage b/tests/run-coverage/test_harness.coverage
index 93bd1cfcb48..ff6009f6fce 100644
--- a/tests/run-coverage/test_harness.coverage
+++ b/tests/run-coverage/test_harness.coverage
@@ -1,11 +1,11 @@
-    1|       |// Verify that the entry point injected by the test harness doesn't cause
-    2|       |// weird artifacts in the coverage report (e.g. issue #10749).
-    3|       |
-    4|       |// compile-flags: --test
-    5|       |
-    6|       |#[allow(dead_code)]
-    7|      0|fn unused() {}
-    8|       |
-    9|      1|#[test]
-   10|      1|fn my_test() {}
+   LL|       |// Verify that the entry point injected by the test harness doesn't cause
+   LL|       |// weird artifacts in the coverage report (e.g. issue #10749).
+   LL|       |
+   LL|       |// compile-flags: --test
+   LL|       |
+   LL|       |#[allow(dead_code)]
+   LL|      0|fn unused() {}
+   LL|       |
+   LL|      1|#[test]
+   LL|      1|fn my_test() {}
 
diff --git a/tests/run-coverage/tight_inf_loop.coverage b/tests/run-coverage/tight_inf_loop.coverage
index 2d4c57f451a..c15c76b3aba 100644
--- a/tests/run-coverage/tight_inf_loop.coverage
+++ b/tests/run-coverage/tight_inf_loop.coverage
@@ -1,6 +1,6 @@
-    1|      1|fn main() {
-    2|      1|    if false {
-    3|      0|        loop {}
-    4|      1|    }
-    5|      1|}
+   LL|      1|fn main() {
+   LL|      1|    if false {
+   LL|      0|        loop {}
+   LL|      1|    }
+   LL|      1|}
 
diff --git a/tests/run-coverage/try_error_result.coverage b/tests/run-coverage/try_error_result.coverage
index efe573a5607..fcdb7437d00 100644
--- a/tests/run-coverage/try_error_result.coverage
+++ b/tests/run-coverage/try_error_result.coverage
@@ -1,125 +1,125 @@
-    1|       |#![allow(unused_assignments)]
-    2|       |// failure-status: 1
-    3|       |
-    4|      6|fn call(return_error: bool) -> Result<(),()> {
-    5|      6|    if return_error {
-    6|      1|        Err(())
-    7|       |    } else {
-    8|      5|        Ok(())
-    9|       |    }
-   10|      6|}
-   11|       |
-   12|      1|fn test1() -> Result<(),()> {
-   13|      1|    let mut
-   14|      1|        countdown = 10
-   15|       |    ;
-   16|       |    for
-   17|       |        _
-   18|       |    in
-   19|      6|        0..10
-   20|       |    {
-   21|      6|        countdown
-   22|      6|            -= 1
-   23|      6|        ;
-   24|      6|        if
-   25|      6|            countdown < 5
-   26|       |        {
-   27|      1|            call(/*return_error=*/ true)?;
-   28|      0|            call(/*return_error=*/ false)?;
-   29|       |        }
-   30|       |        else
-   31|       |        {
-   32|      5|            call(/*return_error=*/ false)?;
+   LL|       |#![allow(unused_assignments)]
+   LL|       |// failure-status: 1
+   LL|       |
+   LL|      6|fn call(return_error: bool) -> Result<(),()> {
+   LL|      6|    if return_error {
+   LL|      1|        Err(())
+   LL|       |    } else {
+   LL|      5|        Ok(())
+   LL|       |    }
+   LL|      6|}
+   LL|       |
+   LL|      1|fn test1() -> Result<(),()> {
+   LL|      1|    let mut
+   LL|      1|        countdown = 10
+   LL|       |    ;
+   LL|       |    for
+   LL|       |        _
+   LL|       |    in
+   LL|      6|        0..10
+   LL|       |    {
+   LL|      6|        countdown
+   LL|      6|            -= 1
+   LL|      6|        ;
+   LL|      6|        if
+   LL|      6|            countdown < 5
+   LL|       |        {
+   LL|      1|            call(/*return_error=*/ true)?;
+   LL|      0|            call(/*return_error=*/ false)?;
+   LL|       |        }
+   LL|       |        else
+   LL|       |        {
+   LL|      5|            call(/*return_error=*/ false)?;
                                                        ^0
-   33|       |        }
-   34|       |    }
-   35|      0|    Ok(())
-   36|      1|}
-   37|       |
-   38|       |struct Thing1;
-   39|       |impl Thing1 {
-   40|     18|    fn get_thing_2(&self, return_error: bool) -> Result<Thing2,()> {
-   41|     18|        if return_error {
-   42|      1|            Err(())
-   43|       |        } else {
-   44|     17|            Ok(Thing2{})
-   45|       |        }
-   46|     18|    }
-   47|       |}
-   48|       |
-   49|       |struct Thing2;
-   50|       |impl Thing2 {
-   51|     17|    fn call(&self, return_error: bool) -> Result<u32,()> {
-   52|     17|        if return_error {
-   53|      2|            Err(())
-   54|       |        } else {
-   55|     15|            Ok(57)
-   56|       |        }
-   57|     17|    }
-   58|       |}
-   59|       |
-   60|      1|fn test2() -> Result<(),()> {
-   61|      1|    let thing1 = Thing1{};
-   62|      1|    let mut
-   63|      1|        countdown = 10
-   64|       |    ;
-   65|       |    for
-   66|       |        _
-   67|       |    in
-   68|      6|        0..10
-   69|       |    {
-   70|      6|        countdown
-   71|      6|            -= 1
-   72|      6|        ;
-   73|      6|        if
-   74|      6|            countdown < 5
-   75|       |        {
-   76|      1|            thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail");
+   LL|       |        }
+   LL|       |    }
+   LL|      0|    Ok(())
+   LL|      1|}
+   LL|       |
+   LL|       |struct Thing1;
+   LL|       |impl Thing1 {
+   LL|     18|    fn get_thing_2(&self, return_error: bool) -> Result<Thing2,()> {
+   LL|     18|        if return_error {
+   LL|      1|            Err(())
+   LL|       |        } else {
+   LL|     17|            Ok(Thing2{})
+   LL|       |        }
+   LL|     18|    }
+   LL|       |}
+   LL|       |
+   LL|       |struct Thing2;
+   LL|       |impl Thing2 {
+   LL|     17|    fn call(&self, return_error: bool) -> Result<u32,()> {
+   LL|     17|        if return_error {
+   LL|      2|            Err(())
+   LL|       |        } else {
+   LL|     15|            Ok(57)
+   LL|       |        }
+   LL|     17|    }
+   LL|       |}
+   LL|       |
+   LL|      1|fn test2() -> Result<(),()> {
+   LL|      1|    let thing1 = Thing1{};
+   LL|      1|    let mut
+   LL|      1|        countdown = 10
+   LL|       |    ;
+   LL|       |    for
+   LL|       |        _
+   LL|       |    in
+   LL|      6|        0..10
+   LL|       |    {
+   LL|      6|        countdown
+   LL|      6|            -= 1
+   LL|      6|        ;
+   LL|      6|        if
+   LL|      6|            countdown < 5
+   LL|       |        {
+   LL|      1|            thing1.get_thing_2(/*err=*/ false)?.call(/*err=*/ true).expect_err("call should fail");
                                                             ^0
-   77|      1|            thing1
-   78|      1|                .
-   79|      1|                get_thing_2(/*return_error=*/ false)
-   80|      0|                ?
-   81|       |                .
-   82|      1|                call(/*return_error=*/ true)
-   83|      1|                .
-   84|      1|                expect_err(
-   85|      1|                    "call should fail"
-   86|      1|                );
-   87|      1|            let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?;
+   LL|      1|            thing1
+   LL|      1|                .
+   LL|      1|                get_thing_2(/*return_error=*/ false)
+   LL|      0|                ?
+   LL|       |                .
+   LL|      1|                call(/*return_error=*/ true)
+   LL|      1|                .
+   LL|      1|                expect_err(
+   LL|      1|                    "call should fail"
+   LL|      1|                );
+   LL|      1|            let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ true)?;
                               ^0                                                ^0                          ^0
-   88|      0|            assert_eq!(val, 57);
-   89|      0|            let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?;
-   90|      0|            assert_eq!(val, 57);
-   91|       |        }
-   92|       |        else
-   93|       |        {
-   94|      5|            let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?;
+   LL|      0|            assert_eq!(val, 57);
+   LL|      0|            let val = thing1.get_thing_2(/*return_error=*/ true)?.call(/*return_error=*/ false)?;
+   LL|      0|            assert_eq!(val, 57);
+   LL|       |        }
+   LL|       |        else
+   LL|       |        {
+   LL|      5|            let val = thing1.get_thing_2(/*return_error=*/ false)?.call(/*return_error=*/ false)?;
                                                                                ^0                             ^0
-   95|      5|            assert_eq!(val, 57);
-   96|      5|            let val = thing1
-   97|      5|                .get_thing_2(/*return_error=*/ false)?
+   LL|      5|            assert_eq!(val, 57);
+   LL|      5|            let val = thing1
+   LL|      5|                .get_thing_2(/*return_error=*/ false)?
                                                                    ^0
-   98|      5|                .call(/*return_error=*/ false)?;
+   LL|      5|                .call(/*return_error=*/ false)?;
                                                             ^0
-   99|      5|            assert_eq!(val, 57);
-  100|      5|            let val = thing1
-  101|      5|                .get_thing_2(/*return_error=*/ false)
-  102|      0|                ?
-  103|      5|                .call(/*return_error=*/ false)
-  104|      0|                ?
-  105|       |                ;
-  106|      5|            assert_eq!(val, 57);
-  107|       |        }
-  108|       |    }
-  109|      0|    Ok(())
-  110|      1|}
-  111|       |
-  112|      1|fn main() -> Result<(),()> {
-  113|      1|    test1().expect_err("test1 should fail");
-  114|      1|    test2()
-  115|      1|    ?
-  116|       |    ;
-  117|      0|    Ok(())
-  118|      1|}
+   LL|      5|            assert_eq!(val, 57);
+   LL|      5|            let val = thing1
+   LL|      5|                .get_thing_2(/*return_error=*/ false)
+   LL|      0|                ?
+   LL|      5|                .call(/*return_error=*/ false)
+   LL|      0|                ?
+   LL|       |                ;
+   LL|      5|            assert_eq!(val, 57);
+   LL|       |        }
+   LL|       |    }
+   LL|      0|    Ok(())
+   LL|      1|}
+   LL|       |
+   LL|      1|fn main() -> Result<(),()> {
+   LL|      1|    test1().expect_err("test1 should fail");
+   LL|      1|    test2()
+   LL|      1|    ?
+   LL|       |    ;
+   LL|      0|    Ok(())
+   LL|      1|}
 
diff --git a/tests/run-coverage/unused.coverage b/tests/run-coverage/unused.coverage
index 15fcf21c0ef..ba25e34bf86 100644
--- a/tests/run-coverage/unused.coverage
+++ b/tests/run-coverage/unused.coverage
@@ -1,62 +1,62 @@
-    1|      2|fn foo<T>(x: T) {
-    2|      2|    let mut i = 0;
-    3|     22|    while i < 10 {
-    4|     20|        i != 0 || i != 0;
+   LL|      2|fn foo<T>(x: T) {
+   LL|      2|    let mut i = 0;
+   LL|     22|    while i < 10 {
+   LL|     20|        i != 0 || i != 0;
                                 ^2
-    5|     20|        i += 1;
-    6|       |    }
-    7|      2|}
+   LL|     20|        i += 1;
+   LL|       |    }
+   LL|      2|}
   ------------------
   | unused::foo::<f32>:
-  |    1|      1|fn foo<T>(x: T) {
-  |    2|      1|    let mut i = 0;
-  |    3|     11|    while i < 10 {
-  |    4|     10|        i != 0 || i != 0;
+  |   LL|      1|fn foo<T>(x: T) {
+  |   LL|      1|    let mut i = 0;
+  |   LL|     11|    while i < 10 {
+  |   LL|     10|        i != 0 || i != 0;
   |                                ^1
-  |    5|     10|        i += 1;
-  |    6|       |    }
-  |    7|      1|}
+  |   LL|     10|        i += 1;
+  |   LL|       |    }
+  |   LL|      1|}
   ------------------
   | unused::foo::<u32>:
-  |    1|      1|fn foo<T>(x: T) {
-  |    2|      1|    let mut i = 0;
-  |    3|     11|    while i < 10 {
-  |    4|     10|        i != 0 || i != 0;
+  |   LL|      1|fn foo<T>(x: T) {
+  |   LL|      1|    let mut i = 0;
+  |   LL|     11|    while i < 10 {
+  |   LL|     10|        i != 0 || i != 0;
   |                                ^1
-  |    5|     10|        i += 1;
-  |    6|       |    }
-  |    7|      1|}
+  |   LL|     10|        i += 1;
+  |   LL|       |    }
+  |   LL|      1|}
   ------------------
-    8|       |
-    9|      0|fn unused_template_func<T>(x: T) {
-   10|      0|    let mut i = 0;
-   11|      0|    while i < 10 {
-   12|      0|        i != 0 || i != 0;
-   13|      0|        i += 1;
-   14|       |    }
-   15|      0|}
-   16|       |
-   17|      0|fn unused_func(mut a: u32) {
-   18|      0|    if a != 0 {
-   19|      0|        a += 1;
-   20|      0|    }
-   21|      0|}
-   22|       |
-   23|      0|fn unused_func2(mut a: u32) {
-   24|      0|    if a != 0 {
-   25|      0|        a += 1;
-   26|      0|    }
-   27|      0|}
-   28|       |
-   29|      0|fn unused_func3(mut a: u32) {
-   30|      0|    if a != 0 {
-   31|      0|        a += 1;
-   32|      0|    }
-   33|      0|}
-   34|       |
-   35|      1|fn main() -> Result<(), u8> {
-   36|      1|    foo::<u32>(0);
-   37|      1|    foo::<f32>(0.0);
-   38|      1|    Ok(())
-   39|      1|}
+   LL|       |
+   LL|      0|fn unused_template_func<T>(x: T) {
+   LL|      0|    let mut i = 0;
+   LL|      0|    while i < 10 {
+   LL|      0|        i != 0 || i != 0;
+   LL|      0|        i += 1;
+   LL|       |    }
+   LL|      0|}
+   LL|       |
+   LL|      0|fn unused_func(mut a: u32) {
+   LL|      0|    if a != 0 {
+   LL|      0|        a += 1;
+   LL|      0|    }
+   LL|      0|}
+   LL|       |
+   LL|      0|fn unused_func2(mut a: u32) {
+   LL|      0|    if a != 0 {
+   LL|      0|        a += 1;
+   LL|      0|    }
+   LL|      0|}
+   LL|       |
+   LL|      0|fn unused_func3(mut a: u32) {
+   LL|      0|    if a != 0 {
+   LL|      0|        a += 1;
+   LL|      0|    }
+   LL|      0|}
+   LL|       |
+   LL|      1|fn main() -> Result<(), u8> {
+   LL|      1|    foo::<u32>(0);
+   LL|      1|    foo::<f32>(0.0);
+   LL|      1|    Ok(())
+   LL|      1|}
 
diff --git a/tests/run-coverage/unused_mod.coverage b/tests/run-coverage/unused_mod.coverage
index e1d82f66f75..558dfaa5cff 100644
--- a/tests/run-coverage/unused_mod.coverage
+++ b/tests/run-coverage/unused_mod.coverage
@@ -1,13 +1,13 @@
 $DIR/auxiliary/unused_mod_helper.rs:
-    1|      0|pub fn never_called_function() {
-    2|      0|    println!("I am never called");
-    3|      0|}
+   LL|      0|pub fn never_called_function() {
+   LL|      0|    println!("I am never called");
+   LL|      0|}
 
 $DIR/unused_mod.rs:
-    1|       |#[path = "auxiliary/unused_mod_helper.rs"]
-    2|       |mod unused_module;
-    3|       |
-    4|      1|fn main() {
-    5|      1|    println!("hello world!");
-    6|      1|}
+   LL|       |#[path = "auxiliary/unused_mod_helper.rs"]
+   LL|       |mod unused_module;
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    println!("hello world!");
+   LL|      1|}
 
diff --git a/tests/run-coverage/uses_crate.coverage b/tests/run-coverage/uses_crate.coverage
index ccdcf350334..9da096dbd50 100644
--- a/tests/run-coverage/uses_crate.coverage
+++ b/tests/run-coverage/uses_crate.coverage
@@ -1,170 +1,170 @@
 $DIR/auxiliary/used_crate.rs:
-    1|       |#![allow(unused_assignments, unused_variables)]
-    2|       |// compile-flags: -C opt-level=3
-    3|       |use std::fmt::Debug; // ^^ validates coverage now works with optimizations
-    4|       |
-    5|      1|pub fn used_function() {
-    6|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    7|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-    8|      1|    // dependent conditions.
-    9|      1|    let is_true = std::env::args().len() == 1;
-   10|      1|    let mut countdown = 0;
-   11|      1|    if is_true {
-   12|      1|        countdown = 10;
-   13|      1|    }
+   LL|       |#![allow(unused_assignments, unused_variables)]
+   LL|       |// compile-flags: -C opt-level=3
+   LL|       |use std::fmt::Debug; // ^^ validates coverage now works with optimizations
+   LL|       |
+   LL|      1|pub fn used_function() {
+   LL|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+   LL|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   LL|      1|    // dependent conditions.
+   LL|      1|    let is_true = std::env::args().len() == 1;
+   LL|      1|    let mut countdown = 0;
+   LL|      1|    if is_true {
+   LL|      1|        countdown = 10;
+   LL|      1|    }
                    ^0
-   14|      1|    use_this_lib_crate();
-   15|      1|}
-   16|       |
-   17|      2|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
-   18|      2|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
-   19|      2|}
+   LL|      1|    use_this_lib_crate();
+   LL|      1|}
+   LL|       |
+   LL|      2|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+   LL|      2|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+   LL|      2|}
   ------------------
   | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
   ------------------
   | used_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>:
-  |   17|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
-  |   18|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
-  |   19|      1|}
+  |   LL|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+  |   LL|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+  |   LL|      1|}
   ------------------
   | used_crate::used_only_from_bin_crate_generic_function::<&str>:
-  |   17|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
-  |   18|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
-  |   19|      1|}
+  |   LL|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+  |   LL|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+  |   LL|      1|}
   ------------------
-   20|       |// Expect for above function: `Unexecuted instantiation` (see below)
-   21|      2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
-   22|      2|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
-   23|      2|}
+   LL|       |// Expect for above function: `Unexecuted instantiation` (see below)
+   LL|      2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+   LL|      2|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+   LL|      2|}
   ------------------
   | used_crate::used_only_from_this_lib_crate_generic_function::<&str>:
-  |   21|      1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
-  |   22|      1|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
-  |   23|      1|}
+  |   LL|      1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   LL|      1|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+  |   LL|      1|}
   ------------------
   | used_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
-  |   21|      1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
-  |   22|      1|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
-  |   23|      1|}
+  |   LL|      1|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   LL|      1|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+  |   LL|      1|}
   ------------------
-   24|       |
-   25|      2|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
-   26|      2|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
-   27|      2|}
+   LL|       |
+   LL|      2|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+   LL|      2|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+   LL|      2|}
   ------------------
   | used_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>:
-  |   25|      1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
-  |   26|      1|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
-  |   27|      1|}
+  |   LL|      1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   LL|      1|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   LL|      1|}
   ------------------
   | used_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
-  |   25|      1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
-  |   26|      1|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
-  |   27|      1|}
+  |   LL|      1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   LL|      1|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   LL|      1|}
   ------------------
-   28|       |
-   29|      2|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
-   30|      2|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
-   31|      2|}
+   LL|       |
+   LL|      2|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+   LL|      2|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+   LL|      2|}
   ------------------
   | used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
-  |   29|      1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
-  |   30|      1|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
-  |   31|      1|}
+  |   LL|      1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   LL|      1|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   LL|      1|}
   ------------------
   | used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
-  |   29|      1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
-  |   30|      1|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
-  |   31|      1|}
+  |   LL|      1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   LL|      1|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   LL|      1|}
   ------------------
-   32|       |
-   33|      0|pub fn unused_generic_function<T: Debug>(arg: T) {
-   34|      0|    println!("unused_generic_function with {:?}", arg);
-   35|      0|}
-   36|       |
-   37|      0|pub fn unused_function() {
-   38|      0|    let is_true = std::env::args().len() == 1;
-   39|      0|    let mut countdown = 2;
-   40|      0|    if !is_true {
-   41|      0|        countdown = 20;
-   42|      0|    }
-   43|      0|}
-   44|       |
-   45|      0|fn unused_private_function() {
-   46|      0|    let is_true = std::env::args().len() == 1;
-   47|      0|    let mut countdown = 2;
-   48|      0|    if !is_true {
-   49|      0|        countdown = 20;
-   50|      0|    }
-   51|      0|}
-   52|       |
-   53|      1|fn use_this_lib_crate() {
-   54|      1|    used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
-   55|      1|    used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
-   56|      1|        "used from library used_crate.rs",
-   57|      1|    );
-   58|      1|    let some_vec = vec![5, 6, 7, 8];
-   59|      1|    used_only_from_this_lib_crate_generic_function(some_vec);
-   60|      1|    used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
-   61|      1|}
-   62|       |
-   63|       |// FIXME(#79651): "Unexecuted instantiation" errors appear in coverage results,
-   64|       |// for example:
-   65|       |//
-   66|       |// | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
-   67|       |//
-   68|       |// These notices appear when `llvm-cov` shows instantiations. This may be a
-   69|       |// default option, but it can be suppressed with:
-   70|       |//
-   71|       |// ```shell
-   72|       |// $ `llvm-cov show --show-instantiations=0 ...`
-   73|       |// ```
-   74|       |//
-   75|       |// The notice is triggered because the function is unused by the library itself,
-   76|       |// and when the library is compiled, a synthetic function is generated, so
-   77|       |// unused function coverage can be reported. Coverage can be skipped for unused
-   78|       |// generic functions with:
-   79|       |//
-   80|       |// ```shell
-   81|       |// $ `rustc -Zunstable-options -C instrument-coverage=except-unused-generics ...`
-   82|       |// ```
-   83|       |//
-   84|       |// Even though this function is used by `uses_crate.rs` (and
-   85|       |// counted), with substitutions for `T`, those instantiations are only generated
-   86|       |// when the generic function is actually used (from the binary, not from this
-   87|       |// library crate). So the test result shows coverage for all instantiated
-   88|       |// versions and their generic type substitutions, plus the `Unexecuted
-   89|       |// instantiation` message for the non-substituted version. This is valid, but
-   90|       |// unfortunately a little confusing.
-   91|       |//
-   92|       |// The library crate has its own coverage map, and the only way to show unused
-   93|       |// coverage of a generic function is to include the generic function in the
-   94|       |// coverage map, marked as an "unused function". If the library were used by
-   95|       |// another binary that never used this generic function, then it would be valid
-   96|       |// to show the unused generic, with unknown substitution (`_`).
-   97|       |//
-   98|       |// The alternative is to exclude all generics from being included in the "unused
-   99|       |// functions" list, which would then omit coverage results for
-  100|       |// `unused_generic_function<T>()`, below.
+   LL|       |
+   LL|      0|pub fn unused_generic_function<T: Debug>(arg: T) {
+   LL|      0|    println!("unused_generic_function with {:?}", arg);
+   LL|      0|}
+   LL|       |
+   LL|      0|pub fn unused_function() {
+   LL|      0|    let is_true = std::env::args().len() == 1;
+   LL|      0|    let mut countdown = 2;
+   LL|      0|    if !is_true {
+   LL|      0|        countdown = 20;
+   LL|      0|    }
+   LL|      0|}
+   LL|       |
+   LL|      0|fn unused_private_function() {
+   LL|      0|    let is_true = std::env::args().len() == 1;
+   LL|      0|    let mut countdown = 2;
+   LL|      0|    if !is_true {
+   LL|      0|        countdown = 20;
+   LL|      0|    }
+   LL|      0|}
+   LL|       |
+   LL|      1|fn use_this_lib_crate() {
+   LL|      1|    used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
+   LL|      1|    used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+   LL|      1|        "used from library used_crate.rs",
+   LL|      1|    );
+   LL|      1|    let some_vec = vec![5, 6, 7, 8];
+   LL|      1|    used_only_from_this_lib_crate_generic_function(some_vec);
+   LL|      1|    used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
+   LL|      1|}
+   LL|       |
+   LL|       |// FIXME(#79651): "Unexecuted instantiation" errors appear in coverage results,
+   LL|       |// for example:
+   LL|       |//
+   LL|       |// | Unexecuted instantiation: used_crate::used_only_from_bin_crate_generic_function::<_>
+   LL|       |//
+   LL|       |// These notices appear when `llvm-cov` shows instantiations. This may be a
+   LL|       |// default option, but it can be suppressed with:
+   LL|       |//
+   LL|       |// ```shell
+   LL|       |// $ `llvm-cov show --show-instantiations=0 ...`
+   LL|       |// ```
+   LL|       |//
+   LL|       |// The notice is triggered because the function is unused by the library itself,
+   LL|       |// and when the library is compiled, a synthetic function is generated, so
+   LL|       |// unused function coverage can be reported. Coverage can be skipped for unused
+   LL|       |// generic functions with:
+   LL|       |//
+   LL|       |// ```shell
+   LL|       |// $ `rustc -Zunstable-options -C instrument-coverage=except-unused-generics ...`
+   LL|       |// ```
+   LL|       |//
+   LL|       |// Even though this function is used by `uses_crate.rs` (and
+   LL|       |// counted), with substitutions for `T`, those instantiations are only generated
+   LL|       |// when the generic function is actually used (from the binary, not from this
+   LL|       |// library crate). So the test result shows coverage for all instantiated
+   LL|       |// versions and their generic type substitutions, plus the `Unexecuted
+   LL|       |// instantiation` message for the non-substituted version. This is valid, but
+   LL|       |// unfortunately a little confusing.
+   LL|       |//
+   LL|       |// The library crate has its own coverage map, and the only way to show unused
+   LL|       |// coverage of a generic function is to include the generic function in the
+   LL|       |// coverage map, marked as an "unused function". If the library were used by
+   LL|       |// another binary that never used this generic function, then it would be valid
+   LL|       |// to show the unused generic, with unknown substitution (`_`).
+   LL|       |//
+   LL|       |// The alternative is to exclude all generics from being included in the "unused
+   LL|       |// functions" list, which would then omit coverage results for
+   LL|       |// `unused_generic_function<T>()`, below.
 
 $DIR/uses_crate.rs:
-    1|       |// This test was failing on Linux for a while due to #110393 somehow making
-    2|       |// the unused functions not instrumented, but it seems to be fine now.
-    3|       |
-    4|       |// Validates coverage now works with optimizations
-    5|       |// compile-flags: -C opt-level=3
-    6|       |
-    7|       |#![allow(unused_assignments, unused_variables)]
-    8|       |
-    9|       |// aux-build:used_crate.rs
-   10|       |extern crate used_crate;
-   11|       |
-   12|      1|fn main() {
-   13|      1|    used_crate::used_function();
-   14|      1|    let some_vec = vec![1, 2, 3, 4];
-   15|      1|    used_crate::used_only_from_bin_crate_generic_function(&some_vec);
-   16|      1|    used_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs");
-   17|      1|    used_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec);
-   18|      1|    used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function("interesting?");
-   19|      1|}
+   LL|       |// This test was failing on Linux for a while due to #110393 somehow making
+   LL|       |// the unused functions not instrumented, but it seems to be fine now.
+   LL|       |
+   LL|       |// Validates coverage now works with optimizations
+   LL|       |// compile-flags: -C opt-level=3
+   LL|       |
+   LL|       |#![allow(unused_assignments, unused_variables)]
+   LL|       |
+   LL|       |// aux-build:used_crate.rs
+   LL|       |extern crate used_crate;
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    used_crate::used_function();
+   LL|      1|    let some_vec = vec![1, 2, 3, 4];
+   LL|      1|    used_crate::used_only_from_bin_crate_generic_function(&some_vec);
+   LL|      1|    used_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs");
+   LL|      1|    used_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec);
+   LL|      1|    used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function("interesting?");
+   LL|      1|}
 
diff --git a/tests/run-coverage/uses_inline_crate.coverage b/tests/run-coverage/uses_inline_crate.coverage
index 64308c796d6..48493e2079c 100644
--- a/tests/run-coverage/uses_inline_crate.coverage
+++ b/tests/run-coverage/uses_inline_crate.coverage
@@ -1,164 +1,164 @@
 $DIR/auxiliary/used_inline_crate.rs:
-    1|       |#![allow(unused_assignments, unused_variables)]
-    2|       |
-    3|       |// compile-flags: -C opt-level=3
-    4|       |// ^^ validates coverage now works with optimizations
-    5|       |use std::fmt::Debug;
-    6|       |
-    7|      1|pub fn used_function() {
-    8|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-    9|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-   10|      1|    // dependent conditions.
-   11|      1|    let is_true = std::env::args().len() == 1;
-   12|      1|    let mut countdown = 0;
-   13|      1|    if is_true {
-   14|      1|        countdown = 10;
-   15|      1|    }
+   LL|       |#![allow(unused_assignments, unused_variables)]
+   LL|       |
+   LL|       |// compile-flags: -C opt-level=3
+   LL|       |// ^^ validates coverage now works with optimizations
+   LL|       |use std::fmt::Debug;
+   LL|       |
+   LL|      1|pub fn used_function() {
+   LL|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+   LL|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   LL|      1|    // dependent conditions.
+   LL|      1|    let is_true = std::env::args().len() == 1;
+   LL|      1|    let mut countdown = 0;
+   LL|      1|    if is_true {
+   LL|      1|        countdown = 10;
+   LL|      1|    }
                    ^0
-   16|      1|    use_this_lib_crate();
-   17|      1|}
-   18|       |
-   19|       |#[inline(always)]
-   20|      1|pub fn used_inline_function() {
-   21|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
-   22|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
-   23|      1|    // dependent conditions.
-   24|      1|    let is_true = std::env::args().len() == 1;
-   25|      1|    let mut countdown = 0;
-   26|      1|    if is_true {
-   27|      1|        countdown = 10;
-   28|      1|    }
+   LL|      1|    use_this_lib_crate();
+   LL|      1|}
+   LL|       |
+   LL|       |#[inline(always)]
+   LL|      1|pub fn used_inline_function() {
+   LL|      1|    // Initialize test constants in a way that cannot be determined at compile time, to ensure
+   LL|      1|    // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from
+   LL|      1|    // dependent conditions.
+   LL|      1|    let is_true = std::env::args().len() == 1;
+   LL|      1|    let mut countdown = 0;
+   LL|      1|    if is_true {
+   LL|      1|        countdown = 10;
+   LL|      1|    }
                    ^0
-   29|      1|    use_this_lib_crate();
-   30|      1|}
-   31|       |
-   32|       |
-   33|       |
-   34|       |
-   35|       |
-   36|       |
-   37|       |
-   38|       |#[inline(always)]
-   39|      2|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
-   40|      2|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
-   41|      2|}
+   LL|      1|    use_this_lib_crate();
+   LL|      1|}
+   LL|       |
+   LL|       |
+   LL|       |
+   LL|       |
+   LL|       |
+   LL|       |
+   LL|       |
+   LL|       |#[inline(always)]
+   LL|      2|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+   LL|      2|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+   LL|      2|}
   ------------------
   | Unexecuted instantiation: used_inline_crate::used_only_from_bin_crate_generic_function::<_>
   ------------------
   | used_inline_crate::used_only_from_bin_crate_generic_function::<&alloc::vec::Vec<i32>>:
-  |   39|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
-  |   40|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
-  |   41|      1|}
+  |   LL|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+  |   LL|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+  |   LL|      1|}
   ------------------
   | used_inline_crate::used_only_from_bin_crate_generic_function::<&str>:
-  |   39|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
-  |   40|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
-  |   41|      1|}
+  |   LL|      1|pub fn used_only_from_bin_crate_generic_function<T: Debug>(arg: T) {
+  |   LL|      1|    println!("used_only_from_bin_crate_generic_function with {:?}", arg);
+  |   LL|      1|}
   ------------------
-   42|       |// Expect for above function: `Unexecuted instantiation` (see notes in `used_crate.rs`)
-   43|       |
-   44|       |#[inline(always)]
-   45|      4|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
-   46|      4|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
-   47|      4|}
+   LL|       |// Expect for above function: `Unexecuted instantiation` (see notes in `used_crate.rs`)
+   LL|       |
+   LL|       |#[inline(always)]
+   LL|      4|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+   LL|      4|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+   LL|      4|}
   ------------------
   | used_inline_crate::used_only_from_this_lib_crate_generic_function::<&str>:
-  |   45|      2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
-  |   46|      2|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
-  |   47|      2|}
+  |   LL|      2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   LL|      2|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+  |   LL|      2|}
   ------------------
   | used_inline_crate::used_only_from_this_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
-  |   45|      2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
-  |   46|      2|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
-  |   47|      2|}
+  |   LL|      2|pub fn used_only_from_this_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   LL|      2|    println!("used_only_from_this_lib_crate_generic_function with {:?}", arg);
+  |   LL|      2|}
   ------------------
-   48|       |
-   49|       |#[inline(always)]
-   50|      3|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
-   51|      3|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
-   52|      3|}
+   LL|       |
+   LL|       |#[inline(always)]
+   LL|      3|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+   LL|      3|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+   LL|      3|}
   ------------------
   | used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<&str>:
-  |   50|      2|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
-  |   51|      2|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
-  |   52|      2|}
+  |   LL|      2|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   LL|      2|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   LL|      2|}
   ------------------
   | used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function::<alloc::vec::Vec<i32>>:
-  |   50|      1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
-  |   51|      1|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
-  |   52|      1|}
+  |   LL|      1|pub fn used_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   LL|      1|    println!("used_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   LL|      1|}
   ------------------
-   53|       |
-   54|       |#[inline(always)]
-   55|      3|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
-   56|      3|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
-   57|      3|}
+   LL|       |
+   LL|       |#[inline(always)]
+   LL|      3|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+   LL|      3|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+   LL|      3|}
   ------------------
   | used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
-  |   55|      1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
-  |   56|      1|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
-  |   57|      1|}
+  |   LL|      1|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   LL|      1|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   LL|      1|}
   ------------------
   | used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function::<&str>:
-  |   55|      2|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
-  |   56|      2|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
-  |   57|      2|}
+  |   LL|      2|pub fn used_with_same_type_from_bin_crate_and_lib_crate_generic_function<T: Debug>(arg: T) {
+  |   LL|      2|    println!("used_with_same_type_from_bin_crate_and_lib_crate_generic_function with {:?}", arg);
+  |   LL|      2|}
   ------------------
-   58|       |
-   59|       |#[inline(always)]
-   60|      0|pub fn unused_generic_function<T: Debug>(arg: T) {
-   61|      0|    println!("unused_generic_function with {:?}", arg);
-   62|      0|}
-   63|       |
-   64|       |#[inline(always)]
-   65|      0|pub fn unused_function() {
-   66|      0|    let is_true = std::env::args().len() == 1;
-   67|      0|    let mut countdown = 2;
-   68|      0|    if !is_true {
-   69|      0|        countdown = 20;
-   70|      0|    }
-   71|      0|}
-   72|       |
-   73|       |#[inline(always)]
-   74|      0|fn unused_private_function() {
-   75|      0|    let is_true = std::env::args().len() == 1;
-   76|      0|    let mut countdown = 2;
-   77|      0|    if !is_true {
-   78|      0|        countdown = 20;
-   79|      0|    }
-   80|      0|}
-   81|       |
-   82|      2|fn use_this_lib_crate() {
-   83|      2|    used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
-   84|      2|    used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
-   85|      2|        "used from library used_crate.rs",
-   86|      2|    );
-   87|      2|    let some_vec = vec![5, 6, 7, 8];
-   88|      2|    used_only_from_this_lib_crate_generic_function(some_vec);
-   89|      2|    used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
-   90|      2|}
+   LL|       |
+   LL|       |#[inline(always)]
+   LL|      0|pub fn unused_generic_function<T: Debug>(arg: T) {
+   LL|      0|    println!("unused_generic_function with {:?}", arg);
+   LL|      0|}
+   LL|       |
+   LL|       |#[inline(always)]
+   LL|      0|pub fn unused_function() {
+   LL|      0|    let is_true = std::env::args().len() == 1;
+   LL|      0|    let mut countdown = 2;
+   LL|      0|    if !is_true {
+   LL|      0|        countdown = 20;
+   LL|      0|    }
+   LL|      0|}
+   LL|       |
+   LL|       |#[inline(always)]
+   LL|      0|fn unused_private_function() {
+   LL|      0|    let is_true = std::env::args().len() == 1;
+   LL|      0|    let mut countdown = 2;
+   LL|      0|    if !is_true {
+   LL|      0|        countdown = 20;
+   LL|      0|    }
+   LL|      0|}
+   LL|       |
+   LL|      2|fn use_this_lib_crate() {
+   LL|      2|    used_from_bin_crate_and_lib_crate_generic_function("used from library used_crate.rs");
+   LL|      2|    used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+   LL|      2|        "used from library used_crate.rs",
+   LL|      2|    );
+   LL|      2|    let some_vec = vec![5, 6, 7, 8];
+   LL|      2|    used_only_from_this_lib_crate_generic_function(some_vec);
+   LL|      2|    used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs");
+   LL|      2|}
 
 $DIR/uses_inline_crate.rs:
-    1|       |// This test was failing on Linux for a while due to #110393 somehow making
-    2|       |// the unused functions not instrumented, but it seems to be fine now.
-    3|       |
-    4|       |// Validates coverage now works with optimizations
-    5|       |// compile-flags: -C opt-level=3
-    6|       |
-    7|       |#![allow(unused_assignments, unused_variables)]
-    8|       |
-    9|       |// aux-build:used_inline_crate.rs
-   10|       |extern crate used_inline_crate;
-   11|       |
-   12|      1|fn main() {
-   13|      1|    used_inline_crate::used_function();
-   14|      1|    used_inline_crate::used_inline_function();
-   15|      1|    let some_vec = vec![1, 2, 3, 4];
-   16|      1|    used_inline_crate::used_only_from_bin_crate_generic_function(&some_vec);
-   17|      1|    used_inline_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs");
-   18|      1|    used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec);
-   19|      1|    used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
-   20|      1|        "interesting?",
-   21|      1|    );
-   22|      1|}
+   LL|       |// This test was failing on Linux for a while due to #110393 somehow making
+   LL|       |// the unused functions not instrumented, but it seems to be fine now.
+   LL|       |
+   LL|       |// Validates coverage now works with optimizations
+   LL|       |// compile-flags: -C opt-level=3
+   LL|       |
+   LL|       |#![allow(unused_assignments, unused_variables)]
+   LL|       |
+   LL|       |// aux-build:used_inline_crate.rs
+   LL|       |extern crate used_inline_crate;
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    used_inline_crate::used_function();
+   LL|      1|    used_inline_crate::used_inline_function();
+   LL|      1|    let some_vec = vec![1, 2, 3, 4];
+   LL|      1|    used_inline_crate::used_only_from_bin_crate_generic_function(&some_vec);
+   LL|      1|    used_inline_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs");
+   LL|      1|    used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec);
+   LL|      1|    used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function(
+   LL|      1|        "interesting?",
+   LL|      1|    );
+   LL|      1|}
 
diff --git a/tests/run-coverage/while.coverage b/tests/run-coverage/while.coverage
index efa7d083f0c..c9d497651c9 100644
--- a/tests/run-coverage/while.coverage
+++ b/tests/run-coverage/while.coverage
@@ -1,6 +1,6 @@
-    1|      1|fn main() {
-    2|      1|    let num = 9;
-    3|      1|    while num >= 10 {
-    4|      0|    }
-    5|      1|}
+   LL|      1|fn main() {
+   LL|      1|    let num = 9;
+   LL|      1|    while num >= 10 {
+   LL|      0|    }
+   LL|      1|}
 
diff --git a/tests/run-coverage/while_early_ret.coverage b/tests/run-coverage/while_early_ret.coverage
index 2ce94e0131d..97808447ab7 100644
--- a/tests/run-coverage/while_early_ret.coverage
+++ b/tests/run-coverage/while_early_ret.coverage
@@ -1,43 +1,43 @@
-    1|       |#![allow(unused_assignments)]
-    2|       |// failure-status: 1
-    3|       |
-    4|      1|fn main() -> Result<(),u8> {
-    5|      1|    let mut countdown = 10;
-    6|       |    while
-    7|      7|        countdown
-    8|      7|            >
-    9|      7|        0
-   10|       |    {
-   11|       |        if
-   12|      7|            countdown
-   13|      7|                <
-   14|      7|            5
-   15|       |        {
-   16|       |            return
-   17|       |                if
-   18|      1|                    countdown
-   19|      1|                        >
-   20|      1|                    8
-   21|       |                {
-   22|      0|                    Ok(())
-   23|       |                }
-   24|       |                else
-   25|       |                {
-   26|      1|                    Err(1)
-   27|       |                }
-   28|       |                ;
-   29|      6|        }
-   30|      6|        countdown
-   31|      6|            -=
-   32|      6|        1
-   33|       |        ;
-   34|       |    }
-   35|      0|    Ok(())
-   36|      1|}
-   37|       |
-   38|       |// ISSUE(77553): Originally, this test had `Err(1)` on line 22 (instead of `Ok(())`) and
-   39|       |// `std::process::exit(2)` on line 26 (instead of `Err(1)`); and this worked as expected on Linux
-   40|       |// and MacOS. But on Windows (MSVC, at least), the call to `std::process::exit()` exits the program
-   41|       |// without saving the InstrProf coverage counters. The use of `std::process:exit()` is not critical
-   42|       |// to the coverage test for early returns, but this is a limitation that should be fixed.
+   LL|       |#![allow(unused_assignments)]
+   LL|       |// failure-status: 1
+   LL|       |
+   LL|      1|fn main() -> Result<(),u8> {
+   LL|      1|    let mut countdown = 10;
+   LL|       |    while
+   LL|      7|        countdown
+   LL|      7|            >
+   LL|      7|        0
+   LL|       |    {
+   LL|       |        if
+   LL|      7|            countdown
+   LL|      7|                <
+   LL|      7|            5
+   LL|       |        {
+   LL|       |            return
+   LL|       |                if
+   LL|      1|                    countdown
+   LL|      1|                        >
+   LL|      1|                    8
+   LL|       |                {
+   LL|      0|                    Ok(())
+   LL|       |                }
+   LL|       |                else
+   LL|       |                {
+   LL|      1|                    Err(1)
+   LL|       |                }
+   LL|       |                ;
+   LL|      6|        }
+   LL|      6|        countdown
+   LL|      6|            -=
+   LL|      6|        1
+   LL|       |        ;
+   LL|       |    }
+   LL|      0|    Ok(())
+   LL|      1|}
+   LL|       |
+   LL|       |// ISSUE(77553): Originally, this test had `Err(1)` on line 22 (instead of `Ok(())`) and
+   LL|       |// `std::process::exit(2)` on line 26 (instead of `Err(1)`); and this worked as expected on Linux
+   LL|       |// and MacOS. But on Windows (MSVC, at least), the call to `std::process::exit()` exits the program
+   LL|       |// without saving the InstrProf coverage counters. The use of `std::process:exit()` is not critical
+   LL|       |// to the coverage test for early returns, but this is a limitation that should be fixed.
 
diff --git a/tests/run-coverage/yield.coverage b/tests/run-coverage/yield.coverage
index 6e2f23ee77b..383dd991500 100644
--- a/tests/run-coverage/yield.coverage
+++ b/tests/run-coverage/yield.coverage
@@ -1,38 +1,38 @@
-    1|       |#![feature(generators, generator_trait)]
-    2|       |#![allow(unused_assignments)]
-    3|       |
-    4|       |use std::ops::{Generator, GeneratorState};
-    5|       |use std::pin::Pin;
-    6|       |
-    7|      1|fn main() {
-    8|      1|    let mut generator = || {
-    9|      1|        yield 1;
-   10|      1|        return "foo"
-   11|      1|    };
-   12|       |
-   13|      1|    match Pin::new(&mut generator).resume(()) {
-   14|      1|        GeneratorState::Yielded(1) => {}
-   15|      0|        _ => panic!("unexpected value from resume"),
-   16|       |    }
-   17|      1|    match Pin::new(&mut generator).resume(()) {
-   18|      1|        GeneratorState::Complete("foo") => {}
-   19|      0|        _ => panic!("unexpected value from resume"),
-   20|       |    }
-   21|       |
-   22|      1|    let mut generator = || {
-   23|      1|        yield 1;
-   24|      1|        yield 2;
-   25|      0|        yield 3;
-   26|      0|        return "foo"
-   27|      0|    };
-   28|       |
-   29|      1|    match Pin::new(&mut generator).resume(()) {
-   30|      1|        GeneratorState::Yielded(1) => {}
-   31|      0|        _ => panic!("unexpected value from resume"),
-   32|       |    }
-   33|      1|    match Pin::new(&mut generator).resume(()) {
-   34|      1|        GeneratorState::Yielded(2) => {}
-   35|      0|        _ => panic!("unexpected value from resume"),
-   36|       |    }
-   37|      1|}
+   LL|       |#![feature(generators, generator_trait)]
+   LL|       |#![allow(unused_assignments)]
+   LL|       |
+   LL|       |use std::ops::{Generator, GeneratorState};
+   LL|       |use std::pin::Pin;
+   LL|       |
+   LL|      1|fn main() {
+   LL|      1|    let mut generator = || {
+   LL|      1|        yield 1;
+   LL|      1|        return "foo"
+   LL|      1|    };
+   LL|       |
+   LL|      1|    match Pin::new(&mut generator).resume(()) {
+   LL|      1|        GeneratorState::Yielded(1) => {}
+   LL|      0|        _ => panic!("unexpected value from resume"),
+   LL|       |    }
+   LL|      1|    match Pin::new(&mut generator).resume(()) {
+   LL|      1|        GeneratorState::Complete("foo") => {}
+   LL|      0|        _ => panic!("unexpected value from resume"),
+   LL|       |    }
+   LL|       |
+   LL|      1|    let mut generator = || {
+   LL|      1|        yield 1;
+   LL|      1|        yield 2;
+   LL|      0|        yield 3;
+   LL|      0|        return "foo"
+   LL|      0|    };
+   LL|       |
+   LL|      1|    match Pin::new(&mut generator).resume(()) {
+   LL|      1|        GeneratorState::Yielded(1) => {}
+   LL|      0|        _ => panic!("unexpected value from resume"),
+   LL|       |    }
+   LL|      1|    match Pin::new(&mut generator).resume(()) {
+   LL|      1|        GeneratorState::Yielded(2) => {}
+   LL|      0|        _ => panic!("unexpected value from resume"),
+   LL|       |    }
+   LL|      1|}
 
diff --git a/tests/run-make/doctests-keep-binaries/Makefile b/tests/run-make/doctests-keep-binaries/Makefile
index 6254e93d333..2c647851ad0 100644
--- a/tests/run-make/doctests-keep-binaries/Makefile
+++ b/tests/run-make/doctests-keep-binaries/Makefile
@@ -3,7 +3,9 @@ include ../tools.mk
 
 # Check that valid binaries are persisted by running them, regardless of whether the --run or --no-run option is used.
 
-all: run no_run
+MY_SRC_DIR := ${CURDIR}
+
+all: run no_run test_run_directory
 
 run:
 	mkdir -p $(TMPDIR)/doctests
@@ -20,3 +22,12 @@ no_run:
 	$(TMPDIR)/doctests/t_rs_2_0/rust_out
 	$(TMPDIR)/doctests/t_rs_8_0/rust_out
 	rm -rf $(TMPDIR)/doctests
+
+# Behavior with --test-run-directory with relative paths.
+test_run_directory:
+	mkdir -p $(TMPDIR)/doctests
+	mkdir -p $(TMPDIR)/rundir
+	$(RUSTC) --crate-type rlib t.rs
+	( cd $(TMPDIR); \
+		$(RUSTDOC) -Zunstable-options --test --persist-doctests doctests --test-run-directory rundir --extern t=libt.rlib $(MY_SRC_DIR)/t.rs )
+	rm -rf $(TMPDIR)/doctests $(TMPDIR)/rundir
diff --git a/tests/run-make/doctests-runtool/Makefile b/tests/run-make/doctests-runtool/Makefile
new file mode 100644
index 00000000000..7d5df1e307f
--- /dev/null
+++ b/tests/run-make/doctests-runtool/Makefile
@@ -0,0 +1,20 @@
+# ignore-cross-compile
+include ../tools.mk
+
+# Tests behavior of rustdoc --runtool
+
+MY_SRC_DIR := ${CURDIR}
+
+all: with_test_run_directory
+
+# Behavior with --runtool with relative paths and --test-run-directory.
+with_test_run_directory:
+	mkdir -p $(TMPDIR)/rundir
+	mkdir -p $(TMPDIR)/runtool
+	$(RUSTC) --crate-type rlib t.rs
+	$(RUSTC) runtool.rs -o $(TMPDIR)/runtool/runtool
+	( cd $(TMPDIR); \
+		$(RUSTDOC) -Zunstable-options --test --test-run-directory rundir \
+			--runtool runtool/runtool --extern t=libt.rlib $(MY_SRC_DIR)/t.rs \
+	)
+	rm -rf $(TMPDIR)/rundir $(TMPDIR)/runtool
diff --git a/tests/run-make/doctests-runtool/runtool.rs b/tests/run-make/doctests-runtool/runtool.rs
new file mode 100644
index 00000000000..f5e3afdf212
--- /dev/null
+++ b/tests/run-make/doctests-runtool/runtool.rs
@@ -0,0 +1,3 @@
+fn main() {
+    eprintln!("{:?}", std::env::args().collect::<Vec<_>>());
+}
diff --git a/tests/run-make/doctests-runtool/t.rs b/tests/run-make/doctests-runtool/t.rs
new file mode 100644
index 00000000000..c38cf0a0b25
--- /dev/null
+++ b/tests/run-make/doctests-runtool/t.rs
@@ -0,0 +1,11 @@
+/// Fungle the foople.
+/// ```
+/// t::foople();
+/// ```
+pub fn foople() {}
+
+/// Flomble the florp
+/// ```
+/// t::florp();
+/// ```
+pub fn florp() {}
diff --git a/tests/run-make/optimization-remarks-dir-pgo/Makefile b/tests/run-make/optimization-remarks-dir-pgo/Makefile
index c88ec1e6cb3..3bc3d7d1428 100644
--- a/tests/run-make/optimization-remarks-dir-pgo/Makefile
+++ b/tests/run-make/optimization-remarks-dir-pgo/Makefile
@@ -1,5 +1,6 @@
 # needs-profiler-support
 # ignore-windows-gnu
+# ignore-cross-compile
 
 # FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
 # properly. Since we only have GCC on the CI ignore the test for now.
diff --git a/tests/run-make/panic-abort-eh_frame/Makefile b/tests/run-make/panic-abort-eh_frame/Makefile
index 1cb7bf575cb..7020455b742 100644
--- a/tests/run-make/panic-abort-eh_frame/Makefile
+++ b/tests/run-make/panic-abort-eh_frame/Makefile
@@ -6,5 +6,5 @@
 include ../tools.mk
 
 all:
-	$(RUSTC) foo.rs --crate-type=lib --emit=obj=$(TMPDIR)/foo.o -Cpanic=abort
+	$(RUSTC) foo.rs --crate-type=lib --emit=obj=$(TMPDIR)/foo.o -Cpanic=abort --edition 2021 -Z validate-mir
 	objdump --dwarf=frames $(TMPDIR)/foo.o | $(CGREP) -v 'DW_CFA'
diff --git a/tests/run-make/panic-abort-eh_frame/foo.rs b/tests/run-make/panic-abort-eh_frame/foo.rs
index e1853529455..e2274d469e7 100644
--- a/tests/run-make/panic-abort-eh_frame/foo.rs
+++ b/tests/run-make/panic-abort-eh_frame/foo.rs
@@ -1,5 +1,13 @@
 #![no_std]
 
+use core::future::Future;
+
+pub struct NeedsDrop;
+
+impl Drop for NeedsDrop {
+    fn drop(&mut self) {}
+}
+
 #[panic_handler]
 fn handler(_: &core::panic::PanicInfo<'_>) -> ! {
     loop {}
@@ -8,3 +16,19 @@ fn handler(_: &core::panic::PanicInfo<'_>) -> ! {
 pub unsafe fn oops(x: *const u32) -> u32 {
     *x
 }
+
+pub async fn foo(_: NeedsDrop) {
+    async fn bar() {}
+    bar().await;
+}
+
+pub fn poll_foo(x: &mut core::task::Context<'_>) {
+    let _g = NeedsDrop;
+    let mut p = core::pin::pin!(foo(NeedsDrop));
+    let _ = p.as_mut().poll(x);
+    let _ = p.as_mut().poll(x);
+}
+
+pub fn drop_foo() {
+    drop(foo(NeedsDrop));
+}
diff --git a/tests/rustdoc-gui/docblock-table.goml b/tests/rustdoc-gui/docblock-table.goml
index 011451ef4f3..678b302f22e 100644
--- a/tests/rustdoc-gui/docblock-table.goml
+++ b/tests/rustdoc-gui/docblock-table.goml
@@ -36,17 +36,17 @@ define-function: (
 )
 
 call-function: ("check-colors", {
-    "theme": "dark",
-    "border_color": "rgb(224, 224, 224)",
-    "zebra_stripe_color": "rgb(42, 42, 42)",
+    "theme": "ayu",
+    "border_color": "#5c6773",
+    "zebra_stripe_color": "#191f26",
 })
 call-function: ("check-colors", {
-    "theme": "ayu",
-    "border_color": "rgb(92, 103, 115)",
-    "zebra_stripe_color": "rgb(25, 31, 38)",
+    "theme": "dark",
+    "border_color": "#e0e0e0",
+    "zebra_stripe_color": "#2a2a2a",
 })
 call-function: ("check-colors", {
     "theme": "light",
-    "border_color": "rgb(224, 224, 224)",
-    "zebra_stripe_color": "rgb(245, 245, 245)",
+    "border_color": "#e0e0e0",
+    "zebra_stripe_color": "#f5f5f5",
 })
diff --git a/tests/rustdoc-gui/search-form-elements.goml b/tests/rustdoc-gui/search-form-elements.goml
index 83c6980909c..a4e22364859 100644
--- a/tests/rustdoc-gui/search-form-elements.goml
+++ b/tests/rustdoc-gui/search-form-elements.goml
@@ -2,262 +2,138 @@
 go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 show-text: true
 
-// Ayu theme
-set-local-storage: {
-    "rustdoc-theme": "ayu",
-    "rustdoc-use-system-theme": "false",
-}
-reload:
-
-assert-css: (
-    ".search-input",
-    {
-        "border-color": "rgb(92, 103, 115)",
-        "background-color": "rgb(20, 25, 32)",
-        "color": "rgb(255, 255, 255)",
-    },
-)
-focus: ".search-input"
-// Nothing should change.
-assert-css: (
-    ".search-input",
-    {
-        "border-color": "rgb(92, 103, 115)",
-        "background-color": "rgb(20, 25, 32)",
-        "color": "rgb(255, 255, 255)",
-    },
-)
-
-assert-css: (
-    "#help-button",
-    {"border-color": "rgb(197, 197, 197)"},
-)
-assert-css: (
-    "#help-button > a",
-    {
-        "color": "rgb(255, 255, 255)",
-        "border-color": "rgb(92, 103, 115)",
-        "background-color": "rgb(20, 25, 32)",
-    },
-)
-move-cursor-to: "#help-button"
-assert-css: (
-    "#help-button:hover",
-    {"border-color": "rgb(197, 197, 197)"},
-)
-// Only "border-color" should change.
-assert-css: (
-    "#help-button:hover > a",
-    {
-        "color": "rgb(255, 255, 255)",
-        "border-color": "rgb(224, 224, 224)",
-        "background-color": "rgb(20, 25, 32)",
-    },
-)
-// Link color inside
-click: "#help-button"
-assert-css: (
-    "#help a",
-    {
-        "color": "rgb(57, 175, 215)",
-    },
-)
-
-assert-css: (
-    "#settings-menu",
-    {"border-color": "rgb(197, 197, 197)"},
-)
-assert-css: (
-    "#settings-menu > a",
-    {
-        "border-color": "rgb(92, 103, 115)",
-        "background-color": "rgb(20, 25, 32)",
-    },
-)
-move-cursor-to: "#settings-menu"
-assert-css: (
-    "#settings-menu:hover",
-    {"border-color": "rgb(197, 197, 197)"},
-)
-// Only "border-color" should change.
-assert-css: (
-    "#settings-menu:hover > a",
-    {
-        "border-color": "rgb(224, 224, 224)",
-        "background-color": "rgb(20, 25, 32)",
-    },
-)
-
-// Dark theme
-set-local-storage: {
-    "rustdoc-theme": "dark",
-    "rustdoc-use-system-theme": "false",
-}
-reload:
-
-assert-css: (
-    ".search-input",
-    {
-        "border-color": "rgb(224, 224, 224)",
-        "background-color": "rgb(240, 240, 240)",
-        "color": "rgb(17, 17, 17)",
-    },
-)
-focus: ".search-input"
-// Only "border-color" should change.
-assert-css: (
-    ".search-input",
-    {
-        "border-color": "rgb(0, 141, 253)",
-        "background-color": "rgb(240, 240, 240)",
-        "color": "rgb(17, 17, 17)",
-    },
-)
-
-assert-css: (
-    "#help-button",
-    {"border-color": "rgb(221, 221, 221)"},
-)
-assert-css: (
-    "#help-button > a",
-    {
-        "color": "rgb(0, 0, 0)",
-        "border-color": "rgb(224, 224, 224)",
-        "background-color": "rgb(240, 240, 240)",
-    },
-)
-move-cursor-to: "#help-button"
-assert-css: (
-    "#help-button:hover",
-    {"border-color": "rgb(221, 221, 221)"},
-)
-// Only "border-color" should change.
-assert-css: (
-    "#help-button:hover > a",
-    {
-        "color": "rgb(0, 0, 0)",
-        "border-color": "rgb(255, 185, 0)",
-        "background-color": "rgb(240, 240, 240)",
-    },
-)
-// Link color inside
-click: "#help-button"
-assert-css: (
-    "#help a",
-    {
-        "color": "rgb(210, 153, 29)",
+define-function: (
+    "check-search-colors",
+    (
+        theme, border, background, search_input_color, search_input_border_focus,
+        menu_button_border, menu_button_a_color, menu_button_a_border_hover, menu_a_color,
+    ),
+    block {
+        set-local-storage: {
+            "rustdoc-theme": |theme|,
+            "rustdoc-use-system-theme": "false",
+        }
+        reload:
+        assert-css: (
+            ".search-input",
+            {
+                "border-color": |border|,
+                "background-color": |background|,
+                "color": |search_input_color|,
+            },
+        )
+        // Focus on search input.
+        focus: ".search-input"
+        assert-css: (
+            ".search-input",
+            {
+                "border-color": |search_input_border_focus|,
+                "background-color": |background|,
+                "color": |search_input_color|,
+            },
+        )
+        assert-css: (
+            "#help-button",
+            {"border-color": |menu_button_border|},
+        )
+        assert-css: (
+            "#help-button > a",
+            {
+                "color": |menu_button_a_color|,
+                "border-color": |border|,
+                "background-color": |background|,
+            },
+        )
+        // Hover help button.
+        move-cursor-to: "#help-button"
+        assert-css: (
+            "#help-button:hover",
+            {"border-color": |menu_button_border|},
+        )
+        assert-css: (
+            "#help-button > a",
+            {
+                "color": |menu_button_a_color|,
+                "border-color": |menu_button_a_border_hover|,
+                "background-color": |background|,
+            },
+        )
+        // Link color inside
+        click: "#help-button"
+        assert-css: (
+            "#help a",
+            {
+                "color": |menu_a_color|,
+            },
+        )
+        assert-css: (
+            "#settings-menu",
+            {"border-color": |menu_button_border|},
+        )
+        assert-css: (
+            "#settings-menu > a",
+            {
+                "color": |menu_button_a_color|,
+                "border-color": |border|,
+                "background-color": |background|,
+            },
+        )
+        // Hover settings menu.
+        move-cursor-to: "#settings-menu"
+        assert-css: (
+            "#settings-menu:hover",
+            {"border-color": |menu_button_border|},
+        )
+        assert-css: (
+            "#settings-menu:hover > a",
+            {
+                "color": |menu_button_a_color|,
+                "border-color": |menu_button_a_border_hover|,
+                "background-color": |background|,
+            },
+        )
     },
 )
 
-assert-css: (
-    "#settings-menu",
-    {"border-color": "rgb(221, 221, 221)"},
-)
-assert-css: (
-    "#settings-menu > a",
-    {
-        "border-color": "rgb(224, 224, 224)",
-        "background-color": "rgb(240, 240, 240)",
-    },
-)
-move-cursor-to: "#settings-menu"
-assert-css: (
-    "#settings-menu:hover",
-    {"border-color": "rgb(221, 221, 221)"},
-)
-// Only "border-color" should change.
-assert-css: (
-    "#settings-menu:hover > a",
-    {
-        "color": "rgb(0, 0, 0)",
-        "border-color": "rgb(255, 185, 0)",
-        "background-color": "rgb(240, 240, 240)",
-    },
-)
-
-// Light theme
-set-local-storage: {
-    "rustdoc-theme": "light",
-    "rustdoc-use-system-theme": "false",
-}
-reload:
-
-assert-css: (
-    ".search-input",
-    {
-        "border-color": "rgb(224, 224, 224)",
-        "background-color": "rgb(255, 255, 255)",
-        "color": "rgb(0, 0, 0)",
-    },
-)
-focus: ".search-input"
-// Nothing should change.
-assert-css: (
-    ".search-input",
-    {
-        "border-color": "rgb(102, 175, 233)",
-        "background-color": "rgb(255, 255, 255)",
-        "color": "rgb(0, 0, 0)",
-    },
-)
-
-assert-css: (
-    "#help-button",
-    {"border-color": "rgb(0, 0, 0)"},
-)
-assert-css: (
-    "#help-button > a",
-    {
-        "color": "rgb(0, 0, 0)",
-        "border-color": "rgb(224, 224, 224)",
-        "background-color": "rgb(255, 255, 255)",
-    },
-)
-move-cursor-to: "#help-button"
-assert-css: (
-    "#help-button:hover",
-    {"border-color": "rgb(0, 0, 0)"},
-)
-// Only "border-color" should change.
-assert-css: (
-    "#help-button:hover > a",
-    {
-        "color": "rgb(0, 0, 0)",
-        "border-color": "rgb(113, 113, 113)",
-        "background-color": "rgb(255, 255, 255)",
-    },
-)
-// Link color inside
-click: "#help-button"
-assert-css: (
-    "#help a",
-    {
-        "color": "rgb(56, 115, 173)",
-    },
-)
-
-assert-css: (
-    "#settings-menu",
-    {"border-color": "rgb(0, 0, 0)"},
-)
-assert-css: (
-    "#settings-menu > a",
-    {
-        "border-color": "rgb(224, 224, 224)",
-        "background-color": "rgb(255, 255, 255)",
-    },
-)
-move-cursor-to: "#settings-menu"
-assert-css: (
-    "#settings-menu:hover",
-    {"border-color": "rgb(0, 0, 0)"},
-)
-// Only "border-color" should change.
-assert-css: (
-    "#settings-menu:hover > a",
-    {
-        "color": "rgb(0, 0, 0)",
-        "border-color": "rgb(113, 113, 113)",
-        "background-color": "rgb(255, 255, 255)",
-    },
+call-function: (
+    "check-search-colors",
+    {
+        "theme": "ayu",
+        "border": "#5c6773",
+        "background": "#141920",
+        "search_input_color": "#fff",
+        "search_input_border_focus": "#5c6773",
+        "menu_button_border": "#c5c5c5",
+        "menu_button_a_color": "#fff",
+        "menu_button_a_border_hover": "#e0e0e0",
+        "menu_a_color": "#39afd7",
+    }
+)
+call-function: (
+    "check-search-colors",
+    {
+        "theme": "dark",
+        "border": "#e0e0e0",
+        "background": "#f0f0f0",
+        "search_input_color": "#111",
+        "search_input_border_focus": "#008dfd",
+        "menu_button_border": "#ddd",
+        "menu_button_a_color": "#000",
+        "menu_button_a_border_hover": "#ffb900",
+        "menu_a_color": "#d2991d",
+    }
+)
+call-function: (
+    "check-search-colors",
+    {
+        "theme": "light",
+        "border": "#e0e0e0",
+        "background": "#fff",
+        "search_input_color": "#000",
+        "search_input_border_focus": "#66afe9",
+        "menu_button_border": "#000",
+        "menu_button_a_color": "#000",
+        "menu_button_a_border_hover": "#717171",
+        "menu_a_color": "#3873ad",
+    }
 )
diff --git a/tests/rustdoc-ui/lints/inline-doc-link.rs b/tests/rustdoc-ui/lints/inline-doc-link.rs
new file mode 100644
index 00000000000..596f89be3d6
--- /dev/null
+++ b/tests/rustdoc-ui/lints/inline-doc-link.rs
@@ -0,0 +1,13 @@
+// Regression test for <https://github.com/rust-lang/rust/pull/113167>
+
+// check-pass
+#![deny(rustdoc::redundant_explicit_links)]
+
+mod m {
+    pub enum ValueEnum {}
+}
+mod m2 {
+    /// [`ValueEnum`]
+    pub use crate::m::ValueEnum;
+}
+pub use m2::ValueEnum;
diff --git a/tests/rustdoc-ui/lints/no-redundancy.rs b/tests/rustdoc-ui/lints/no-redundancy.rs
new file mode 100644
index 00000000000..e3358728b1b
--- /dev/null
+++ b/tests/rustdoc-ui/lints/no-redundancy.rs
@@ -0,0 +1,7 @@
+// check-pass
+
+#![deny(rustdoc::redundant_explicit_links)]
+
+/// [Vec][std::vec::Vec#examples] should not warn, because it's not actually redundant!
+/// [This is just an `Option`][std::option::Option] has different display content to actual link!
+pub fn func() {}
diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links.fixed b/tests/rustdoc-ui/lints/redundant_explicit_links.fixed
new file mode 100644
index 00000000000..900234e31e9
--- /dev/null
+++ b/tests/rustdoc-ui/lints/redundant_explicit_links.fixed
@@ -0,0 +1,158 @@
+// run-rustfix
+
+#![deny(rustdoc::redundant_explicit_links)]
+
+pub fn dummy_target() {}
+
+/// [dummy_target]
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`]
+//~^ ERROR redundant explicit link target
+///
+/// [Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`]
+//~^ ERROR redundant explicit link target
+/// [Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`]
+//~^ ERROR redundant explicit link target
+///
+/// [usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`]
+//~^ ERROR redundant explicit link target
+/// [usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`]
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target] TEXT
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`] TEXT
+//~^ ERROR redundant explicit link target
+pub fn should_warn_inline() {}
+
+/// [`Vec<T>`](Vec)
+/// [`Vec<T>`](std::vec::Vec)
+pub fn should_not_warn_inline() {}
+
+/// [dummy_target]
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`]
+//~^ ERROR redundant explicit link target
+///
+/// [Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`]
+//~^ ERROR redundant explicit link target
+/// [Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`]
+//~^ ERROR redundant explicit link target
+///
+/// [usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`]
+//~^ ERROR redundant explicit link target
+/// [usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`]
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target] TEXT
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`] TEXT
+//~^ ERROR redundant explicit link target
+pub fn should_warn_reference_unknown() {}
+
+/// [`Vec<T>`][Vec]
+/// [`Vec<T>`][std::vec::Vec]
+pub fn should_not_warn_reference_unknown() {}
+
+/// [dummy_target]
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`]
+//~^ ERROR redundant explicit link target
+///
+/// [Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`]
+//~^ ERROR redundant explicit link target
+/// [Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`]
+//~^ ERROR redundant explicit link target
+///
+/// [usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`]
+//~^ ERROR redundant explicit link target
+/// [usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`]
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target] TEXT
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`] TEXT
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target]: dummy_target
+/// [Vec]: Vec
+/// [std::vec::Vec]: Vec
+/// [usize]: usize
+/// [std::primitive::usize]: usize
+pub fn should_warn_reference() {}
+
+/// [`Vec<T>`]: Vec
+/// [`Vec<T>`]: std::vec::Vec
+pub fn should_not_warn_reference() {}
diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links.rs b/tests/rustdoc-ui/lints/redundant_explicit_links.rs
new file mode 100644
index 00000000000..13feb85e051
--- /dev/null
+++ b/tests/rustdoc-ui/lints/redundant_explicit_links.rs
@@ -0,0 +1,158 @@
+// run-rustfix
+
+#![deny(rustdoc::redundant_explicit_links)]
+
+pub fn dummy_target() {}
+
+/// [dummy_target](dummy_target)
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`](dummy_target)
+//~^ ERROR redundant explicit link target
+///
+/// [Vec](Vec)
+//~^ ERROR redundant explicit link target
+/// [`Vec`](Vec)
+//~^ ERROR redundant explicit link target
+/// [Vec](std::vec::Vec)
+//~^ ERROR redundant explicit link target
+/// [`Vec`](std::vec::Vec)
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec](Vec)
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`](Vec)
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec](std::vec::Vec)
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`](std::vec::Vec)
+//~^ ERROR redundant explicit link target
+///
+/// [usize](usize)
+//~^ ERROR redundant explicit link target
+/// [`usize`](usize)
+//~^ ERROR redundant explicit link target
+/// [usize](std::primitive::usize)
+//~^ ERROR redundant explicit link target
+/// [`usize`](std::primitive::usize)
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize](usize)
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`](usize)
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize](std::primitive::usize)
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`](std::primitive::usize)
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target](dummy_target) TEXT
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`](dummy_target) TEXT
+//~^ ERROR redundant explicit link target
+pub fn should_warn_inline() {}
+
+/// [`Vec<T>`](Vec)
+/// [`Vec<T>`](std::vec::Vec)
+pub fn should_not_warn_inline() {}
+
+/// [dummy_target][dummy_target]
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`][dummy_target]
+//~^ ERROR redundant explicit link target
+///
+/// [Vec][Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`][Vec]
+//~^ ERROR redundant explicit link target
+/// [Vec][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec][Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`][Vec]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+///
+/// [usize][usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`][usize]
+//~^ ERROR redundant explicit link target
+/// [usize][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize][usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`][usize]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target][dummy_target] TEXT
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`][dummy_target] TEXT
+//~^ ERROR redundant explicit link target
+pub fn should_warn_reference_unknown() {}
+
+/// [`Vec<T>`][Vec]
+/// [`Vec<T>`][std::vec::Vec]
+pub fn should_not_warn_reference_unknown() {}
+
+/// [dummy_target][dummy_target]
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`][dummy_target]
+//~^ ERROR redundant explicit link target
+///
+/// [Vec][Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`][Vec]
+//~^ ERROR redundant explicit link target
+/// [Vec][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec][Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`][Vec]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+///
+/// [usize][usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`][usize]
+//~^ ERROR redundant explicit link target
+/// [usize][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize][usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`][usize]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target][dummy_target] TEXT
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`][dummy_target] TEXT
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target]: dummy_target
+/// [Vec]: Vec
+/// [std::vec::Vec]: Vec
+/// [usize]: usize
+/// [std::primitive::usize]: usize
+pub fn should_warn_reference() {}
+
+/// [`Vec<T>`]: Vec
+/// [`Vec<T>`]: std::vec::Vec
+pub fn should_not_warn_reference() {}
diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links.stderr b/tests/rustdoc-ui/lints/redundant_explicit_links.stderr
new file mode 100644
index 00000000000..34ec9be6646
--- /dev/null
+++ b/tests/rustdoc-ui/lints/redundant_explicit_links.stderr
@@ -0,0 +1,1007 @@
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:7:20
+   |
+LL | /// [dummy_target](dummy_target)
+   |      ------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+note: the lint level is defined here
+  --> $DIR/redundant_explicit_links.rs:3:9
+   |
+LL | #![deny(rustdoc::redundant_explicit_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: remove explicit link target
+   |
+LL | /// [dummy_target]
+   |     ~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:9:22
+   |
+LL | /// [`dummy_target`](dummy_target)
+   |      --------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`dummy_target`]
+   |     ~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:12:11
+   |
+LL | /// [Vec](Vec)
+   |      ---  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [Vec]
+   |     ~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:14:13
+   |
+LL | /// [`Vec`](Vec)
+   |      -----  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`Vec`]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:16:11
+   |
+LL | /// [Vec](std::vec::Vec)
+   |      ---  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [Vec]
+   |     ~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:18:13
+   |
+LL | /// [`Vec`](std::vec::Vec)
+   |      -----  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`Vec`]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:20:21
+   |
+LL | /// [std::vec::Vec](Vec)
+   |      -------------  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::vec::Vec]
+   |     ~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:22:23
+   |
+LL | /// [`std::vec::Vec`](Vec)
+   |      ---------------  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::vec::Vec`]
+   |     ~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:24:21
+   |
+LL | /// [std::vec::Vec](std::vec::Vec)
+   |      -------------  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::vec::Vec]
+   |     ~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:26:23
+   |
+LL | /// [`std::vec::Vec`](std::vec::Vec)
+   |      ---------------  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::vec::Vec`]
+   |     ~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:29:13
+   |
+LL | /// [usize](usize)
+   |      -----  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [usize]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:31:15
+   |
+LL | /// [`usize`](usize)
+   |      -------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`usize`]
+   |     ~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:33:13
+   |
+LL | /// [usize](std::primitive::usize)
+   |      -----  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [usize]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:35:15
+   |
+LL | /// [`usize`](std::primitive::usize)
+   |      -------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`usize`]
+   |     ~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:37:29
+   |
+LL | /// [std::primitive::usize](usize)
+   |      ---------------------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::primitive::usize]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:39:31
+   |
+LL | /// [`std::primitive::usize`](usize)
+   |      -----------------------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::primitive::usize`]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:41:29
+   |
+LL | /// [std::primitive::usize](std::primitive::usize)
+   |      ---------------------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::primitive::usize]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:43:31
+   |
+LL | /// [`std::primitive::usize`](std::primitive::usize)
+   |      -----------------------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::primitive::usize`]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:46:20
+   |
+LL | /// [dummy_target](dummy_target) TEXT
+   |      ------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [dummy_target] TEXT
+   |     ~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:48:22
+   |
+LL | /// [`dummy_target`](dummy_target) TEXT
+   |      --------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`dummy_target`] TEXT
+   |     ~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:56:20
+   |
+LL | /// [dummy_target][dummy_target]
+   |      ------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [dummy_target]
+   |     ~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:58:22
+   |
+LL | /// [`dummy_target`][dummy_target]
+   |      --------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`dummy_target`]
+   |     ~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:61:11
+   |
+LL | /// [Vec][Vec]
+   |      ---  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [Vec]
+   |     ~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:63:13
+   |
+LL | /// [`Vec`][Vec]
+   |      -----  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`Vec`]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:65:11
+   |
+LL | /// [Vec][std::vec::Vec]
+   |      ---  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [Vec]
+   |     ~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:67:13
+   |
+LL | /// [`Vec`][std::vec::Vec]
+   |      -----  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`Vec`]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:69:21
+   |
+LL | /// [std::vec::Vec][Vec]
+   |      -------------  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::vec::Vec]
+   |     ~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:71:23
+   |
+LL | /// [`std::vec::Vec`][Vec]
+   |      ---------------  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::vec::Vec`]
+   |     ~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:73:21
+   |
+LL | /// [std::vec::Vec][std::vec::Vec]
+   |      -------------  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::vec::Vec]
+   |     ~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:75:23
+   |
+LL | /// [`std::vec::Vec`][std::vec::Vec]
+   |      ---------------  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::vec::Vec`]
+   |     ~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:78:13
+   |
+LL | /// [usize][usize]
+   |      -----  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [usize]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:80:15
+   |
+LL | /// [`usize`][usize]
+   |      -------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`usize`]
+   |     ~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:82:13
+   |
+LL | /// [usize][std::primitive::usize]
+   |      -----  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [usize]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:84:15
+   |
+LL | /// [`usize`][std::primitive::usize]
+   |      -------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`usize`]
+   |     ~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:86:29
+   |
+LL | /// [std::primitive::usize][usize]
+   |      ---------------------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::primitive::usize]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:88:31
+   |
+LL | /// [`std::primitive::usize`][usize]
+   |      -----------------------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::primitive::usize`]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:90:29
+   |
+LL | /// [std::primitive::usize][std::primitive::usize]
+   |      ---------------------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::primitive::usize]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:92:31
+   |
+LL | /// [`std::primitive::usize`][std::primitive::usize]
+   |      -----------------------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::primitive::usize`]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:95:20
+   |
+LL | /// [dummy_target][dummy_target] TEXT
+   |      ------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [dummy_target] TEXT
+   |     ~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:97:22
+   |
+LL | /// [`dummy_target`][dummy_target] TEXT
+   |      --------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`dummy_target`] TEXT
+   |     ~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:105:20
+   |
+LL | /// [dummy_target][dummy_target]
+   |      ------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:149:21
+   |
+LL | /// [dummy_target]: dummy_target
+   |                     ^^^^^^^^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [dummy_target]
+   |     ~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:107:22
+   |
+LL | /// [`dummy_target`][dummy_target]
+   |      --------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:149:21
+   |
+LL | /// [dummy_target]: dummy_target
+   |                     ^^^^^^^^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`dummy_target`]
+   |     ~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:110:11
+   |
+LL | /// [Vec][Vec]
+   |      ---  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:150:12
+   |
+LL | /// [Vec]: Vec
+   |            ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [Vec]
+   |     ~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:112:13
+   |
+LL | /// [`Vec`][Vec]
+   |      -----  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:150:12
+   |
+LL | /// [Vec]: Vec
+   |            ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`Vec`]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:114:11
+   |
+LL | /// [Vec][std::vec::Vec]
+   |      ---  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:151:22
+   |
+LL | /// [std::vec::Vec]: Vec
+   |                      ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [Vec]
+   |     ~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:116:13
+   |
+LL | /// [`Vec`][std::vec::Vec]
+   |      -----  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:151:22
+   |
+LL | /// [std::vec::Vec]: Vec
+   |                      ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`Vec`]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:118:21
+   |
+LL | /// [std::vec::Vec][Vec]
+   |      -------------  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:150:12
+   |
+LL | /// [Vec]: Vec
+   |            ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::vec::Vec]
+   |     ~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:120:23
+   |
+LL | /// [`std::vec::Vec`][Vec]
+   |      ---------------  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:150:12
+   |
+LL | /// [Vec]: Vec
+   |            ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::vec::Vec`]
+   |     ~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:122:21
+   |
+LL | /// [std::vec::Vec][std::vec::Vec]
+   |      -------------  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:151:22
+   |
+LL | /// [std::vec::Vec]: Vec
+   |                      ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::vec::Vec]
+   |     ~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:124:23
+   |
+LL | /// [`std::vec::Vec`][std::vec::Vec]
+   |      ---------------  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:151:22
+   |
+LL | /// [std::vec::Vec]: Vec
+   |                      ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::vec::Vec`]
+   |     ~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:127:13
+   |
+LL | /// [usize][usize]
+   |      -----  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:152:14
+   |
+LL | /// [usize]: usize
+   |              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [usize]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:129:15
+   |
+LL | /// [`usize`][usize]
+   |      -------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:152:14
+   |
+LL | /// [usize]: usize
+   |              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`usize`]
+   |     ~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:131:13
+   |
+LL | /// [usize][std::primitive::usize]
+   |      -----  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:153:30
+   |
+LL | /// [std::primitive::usize]: usize
+   |                              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [usize]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:133:15
+   |
+LL | /// [`usize`][std::primitive::usize]
+   |      -------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:153:30
+   |
+LL | /// [std::primitive::usize]: usize
+   |                              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`usize`]
+   |     ~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:135:29
+   |
+LL | /// [std::primitive::usize][usize]
+   |      ---------------------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:152:14
+   |
+LL | /// [usize]: usize
+   |              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::primitive::usize]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:137:31
+   |
+LL | /// [`std::primitive::usize`][usize]
+   |      -----------------------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:152:14
+   |
+LL | /// [usize]: usize
+   |              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::primitive::usize`]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:139:29
+   |
+LL | /// [std::primitive::usize][std::primitive::usize]
+   |      ---------------------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:153:30
+   |
+LL | /// [std::primitive::usize]: usize
+   |                              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::primitive::usize]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:141:31
+   |
+LL | /// [`std::primitive::usize`][std::primitive::usize]
+   |      -----------------------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:153:30
+   |
+LL | /// [std::primitive::usize]: usize
+   |                              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::primitive::usize`]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:144:20
+   |
+LL | /// [dummy_target][dummy_target] TEXT
+   |      ------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:149:21
+   |
+LL | /// [dummy_target]: dummy_target
+   |                     ^^^^^^^^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [dummy_target] TEXT
+   |     ~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:146:22
+   |
+LL | /// [`dummy_target`][dummy_target] TEXT
+   |      --------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:149:21
+   |
+LL | /// [dummy_target]: dummy_target
+   |                     ^^^^^^^^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`dummy_target`] TEXT
+   |     ~~~~~~~~~~~~~~~~
+
+error: aborting due to 60 previous errors
+
diff --git a/tests/rustdoc-ui/unescaped_backticks.rs b/tests/rustdoc-ui/unescaped_backticks.rs
index e99cd1f3d58..e960e9f59e9 100644
--- a/tests/rustdoc-ui/unescaped_backticks.rs
+++ b/tests/rustdoc-ui/unescaped_backticks.rs
@@ -1,6 +1,7 @@
 #![deny(rustdoc::unescaped_backticks)]
 #![allow(rustdoc::broken_intra_doc_links)]
 #![allow(rustdoc::invalid_html_tags)]
+#![allow(rustdoc::redundant_explicit_links)]
 
 ///
 pub fn empty() {}
diff --git a/tests/rustdoc-ui/unescaped_backticks.stderr b/tests/rustdoc-ui/unescaped_backticks.stderr
index bf1f18889c4..83822f778d0 100644
--- a/tests/rustdoc-ui/unescaped_backticks.stderr
+++ b/tests/rustdoc-ui/unescaped_backticks.stderr
@@ -1,5 +1,5 @@
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:186:70
+  --> $DIR/unescaped_backticks.rs:187:70
    |
 LL | /// if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect =
    |                                                                      ^
@@ -19,7 +19,7 @@ LL | /// if you want your MIR to be modified by the full MIR pipeline, or \`#![c
    |                                                                      +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:231:13
+  --> $DIR/unescaped_backticks.rs:232:13
    |
 LL |         //! `#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")]
    |             ^
@@ -34,7 +34,7 @@ LL |         //! \`#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kin
    |             +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:236:13
+  --> $DIR/unescaped_backticks.rs:237:13
    |
 LL |         /// `cfg=...
    |             ^
@@ -49,7 +49,7 @@ LL |         /// \`cfg=...
    |             +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:240:42
+  --> $DIR/unescaped_backticks.rs:241:42
    |
 LL |         /// `cfg=... and not `#[cfg_attr]`
    |                                          ^
@@ -64,7 +64,7 @@ LL |         /// `cfg=... and not `#[cfg_attr]\`
    |                                          +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:192:91
+  --> $DIR/unescaped_backticks.rs:193:91
    |
 LL |     /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to
    |                                                                                           ^
@@ -79,7 +79,7 @@ LL |     /// Constructs a `TyKind::Error` type and registers a `delay_span_bug`
    |                                                                                           +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:201:34
+  --> $DIR/unescaped_backticks.rs:202:34
    |
 LL |         /// in `nt_to_tokenstream`
    |                                  ^
@@ -94,7 +94,7 @@ LL |         /// in `nt_to_tokenstream\`
    |                                  +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:207:62
+  --> $DIR/unescaped_backticks.rs:208:62
    |
 LL |     /// that `Option<Symbol>` only takes up 4 bytes, because `newtype_index! reserves
    |                                                              ^
@@ -109,7 +109,7 @@ LL |     /// that `Option<Symbol>` only takes up 4 bytes, because \`newtype_inde
    |                                                              +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:215:52
+  --> $DIR/unescaped_backticks.rs:216:52
    |
 LL |     /// also avoids the need to import `OpenOptions`.
    |                                                    ^
@@ -124,7 +124,7 @@ LL |     /// also avoids the need to import `OpenOptions\`.
    |                                                    +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:220:46
+  --> $DIR/unescaped_backticks.rs:221:46
    |
 LL |     /// `HybridBitSet`. Has no effect if `row` does not exist.
    |                                              ^
@@ -139,7 +139,7 @@ LL |     /// `HybridBitSet`. Has no effect if `row\` does not exist.
    |                                              +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:246:12
+  --> $DIR/unescaped_backticks.rs:247:12
    |
 LL |     /// RWU`s can get very large, so it uses a more compact representation.
    |            ^
@@ -154,7 +154,7 @@ LL |     /// RWU\`s can get very large, so it uses a more compact representation
    |            +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:253:15
+  --> $DIR/unescaped_backticks.rs:254:15
    |
 LL |     /// in `U2`.
    |               ^
@@ -169,7 +169,7 @@ LL |     /// in `U2\`.
    |               +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:270:42
+  --> $DIR/unescaped_backticks.rs:271:42
    |
 LL |     /// because it contains `[type error]`. Yuck! (See issue #29857 for
    |                                          ^
@@ -184,7 +184,7 @@ LL |     /// because it contains `[type error]\`. Yuck! (See issue #29857 for
    |                                          +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:280:53
+  --> $DIR/unescaped_backticks.rs:281:53
    |
 LL |     /// well as the second instance of `A: AutoTrait`) to suppress
    |                                                     ^
@@ -199,7 +199,7 @@ LL |     /// well as the second instance of `A: AutoTrait\`) to suppress
    |                                                     +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:290:40
+  --> $DIR/unescaped_backticks.rs:291:40
    |
 LL |     /// `'a` with `'b` and not `'static`. But it will have to do for
    |                                        ^
@@ -211,7 +211,7 @@ LL |     /// `'a` with `'b` and not `'static\`. But it will have to do for
    |                                        +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:299:54
+  --> $DIR/unescaped_backticks.rs:300:54
    |
 LL | /// `None`. Otherwise, it will return `Some(Dispatch)`.
    |                                                      ^
@@ -226,7 +226,7 @@ LL | /// `None`. Otherwise, it will return `Some(Dispatch)\`.
    |                                                      +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:303:13
+  --> $DIR/unescaped_backticks.rs:304:13
    |
 LL | /// or `None` if it isn't.
    |             ^
@@ -238,7 +238,7 @@ LL | /// or `None\` if it isn't.
    |             +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:307:14
+  --> $DIR/unescaped_backticks.rs:308:14
    |
 LL | /// `on_event` should be called.
    |              ^
@@ -253,7 +253,7 @@ LL | /// `on_event\` should be called.
    |              +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:312:29
+  --> $DIR/unescaped_backticks.rs:313:29
    |
 LL | /// [`rebuild_interest_cache`][rebuild] is called after the value of the max
    |                             ^
@@ -268,7 +268,7 @@ LL | /// [`rebuild_interest_cache\`][rebuild] is called after the value of the m
    |                             +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:322:5
+  --> $DIR/unescaped_backticks.rs:323:5
    |
 LL | /     /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
 LL | |
@@ -287,7 +287,7 @@ LL | |     /// level changes.
            to this: `None`. Otherwise, it will return `Some(Dispatch)\`.
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:322:5
+  --> $DIR/unescaped_backticks.rs:323:5
    |
 LL | /     /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
 LL | |
@@ -304,7 +304,7 @@ LL | |     /// level changes.
            to this: or `None\` if it isn't.
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:322:5
+  --> $DIR/unescaped_backticks.rs:323:5
    |
 LL | /     /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
 LL | |
@@ -323,7 +323,7 @@ LL | |     /// level changes.
            to this: `on_event\` should be called.
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:322:5
+  --> $DIR/unescaped_backticks.rs:323:5
    |
 LL | /     /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
 LL | |
@@ -342,7 +342,7 @@ LL | |     /// level changes.
            to this: [`rebuild_interest_cache\`][rebuild] is called after the value of the max
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:348:56
+  --> $DIR/unescaped_backticks.rs:349:56
    |
 LL |     /// instead and use [`CloneCounterObserver::counter`] to increment.
    |                                                        ^
@@ -354,7 +354,7 @@ LL |     /// instead and use [`CloneCounterObserver::counter\`] to increment.
    |                                                        +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:11:5
+  --> $DIR/unescaped_backticks.rs:12:5
    |
 LL | /// `
    |     ^
@@ -366,7 +366,7 @@ LL | /// \`
    |     +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:18:7
+  --> $DIR/unescaped_backticks.rs:19:7
    |
 LL | /// \`
    |       ^
@@ -381,7 +381,7 @@ LL | /// \\`
    |       +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:25:6
+  --> $DIR/unescaped_backticks.rs:26:6
    |
 LL | /// [`link1]
    |      ^
@@ -396,7 +396,7 @@ LL | /// [\`link1]
    |      +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:29:11
+  --> $DIR/unescaped_backticks.rs:30:11
    |
 LL | /// [link2`]
    |           ^
@@ -411,7 +411,7 @@ LL | /// [link2\`]
    |           +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:33:6
+  --> $DIR/unescaped_backticks.rs:34:6
    |
 LL | /// [`link_long](link_long)
    |      ^
@@ -426,7 +426,7 @@ LL | /// [\`link_long](link_long)
    |      +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:37:6
+  --> $DIR/unescaped_backticks.rs:38:6
    |
 LL | /// [`broken-link]
    |      ^
@@ -441,7 +441,7 @@ LL | /// [\`broken-link]
    |      +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:44:8
+  --> $DIR/unescaped_backticks.rs:45:8
    |
 LL | /// <x:`>
    |        ^
@@ -456,7 +456,7 @@ LL | /// <x:\`>
    |        +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:54:6
+  --> $DIR/unescaped_backticks.rs:55:6
    |
 LL | /// 🦀`🦀
    |       ^
@@ -475,7 +475,7 @@ LL | /// 🦀\`🦀
    |       +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:58:5
+  --> $DIR/unescaped_backticks.rs:59:5
    |
 LL | /// `foo(
    |     ^
@@ -490,7 +490,7 @@ LL | /// \`foo(
    |     +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:64:14
+  --> $DIR/unescaped_backticks.rs:65:14
    |
 LL | /// `foo `bar`
    |              ^
@@ -505,7 +505,7 @@ LL | /// `foo `bar\`
    |              +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:70:5
+  --> $DIR/unescaped_backticks.rs:71:5
    |
 LL | /// `foo(
    |     ^
@@ -520,7 +520,7 @@ LL | /// \`foo(
    |     +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:75:83
+  --> $DIR/unescaped_backticks.rs:76:83
    |
 LL | /// Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`.
    |                                                                                   ^
@@ -535,7 +535,7 @@ LL | /// Addition is commutative, which means that add(a, b)` is the same as `ad
    |                                                                                   +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:79:51
+  --> $DIR/unescaped_backticks.rs:80:51
    |
 LL | /// or even to add a number `n` to 42 (`add(42, b)`)!
    |                                                   ^
@@ -550,7 +550,7 @@ LL | /// or even to add a number `n` to 42 (`add(42, b)\`)!
    |                                                   +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:83:83
+  --> $DIR/unescaped_backticks.rs:84:83
    |
 LL | /// Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`.
    |                                                                                   ^
@@ -565,7 +565,7 @@ LL | /// Addition is commutative, which means that `add(a, b) is the same as `ad
    |                                                                                   +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:87:51
+  --> $DIR/unescaped_backticks.rs:88:51
    |
 LL | /// or even to add a number `n` to 42 (`add(42, n)`)!
    |                                                   ^
@@ -580,7 +580,7 @@ LL | /// or even to add a number `n` to 42 (`add(42, n)\`)!
    |                                                   +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:91:83
+  --> $DIR/unescaped_backticks.rs:92:83
    |
 LL | /// Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`.
    |                                                                                   ^
@@ -595,7 +595,7 @@ LL | /// Addition is commutative, which means that `add(a, b)` is the same as ad
    |                                                                                   +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:95:50
+  --> $DIR/unescaped_backticks.rs:96:50
    |
 LL | /// or even to add a number `n` to 42 (add(42, n)`)!
    |                                                  ^
@@ -610,7 +610,7 @@ LL | /// or even to add a number `n` to 42 (add(42, n)\`)!
    |                                                  +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:99:74
+  --> $DIR/unescaped_backticks.rs:100:74
    |
 LL | /// Addition is commutative, which means that `add(a, b)` is the same as `add(b, a).
    |                                                                          ^
@@ -625,7 +625,7 @@ LL | /// Addition is commutative, which means that `add(a, b)` is the same as \`
    |                                                                          +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:103:51
+  --> $DIR/unescaped_backticks.rs:104:51
    |
 LL | /// or even to add a number `n` to 42 (`add(42, n)`)!
    |                                                   ^
@@ -640,7 +640,7 @@ LL | /// or even to add a number `n` to 42 (`add(42, n)\`)!
    |                                                   +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:107:1
+  --> $DIR/unescaped_backticks.rs:108:1
    |
 LL | #[doc = "`"]
    | ^^^^^^^^^^^^
@@ -651,7 +651,7 @@ LL | #[doc = "`"]
            to this: \`
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:114:1
+  --> $DIR/unescaped_backticks.rs:115:1
    |
 LL | #[doc = concat!("\\", "`")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -664,7 +664,7 @@ LL | #[doc = concat!("\\", "`")]
            to this: \\`
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:118:1
+  --> $DIR/unescaped_backticks.rs:119:1
    |
 LL | #[doc = "Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`."]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -677,7 +677,7 @@ LL | #[doc = "Addition is commutative, which means that add(a, b)` is the same a
            to this: Addition is commutative, which means that add(a, b)` is the same as `add(b, a)\`.
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:122:1
+  --> $DIR/unescaped_backticks.rs:123:1
    |
 LL | #[doc = "Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`."]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -690,7 +690,7 @@ LL | #[doc = "Addition is commutative, which means that `add(a, b) is the same a
            to this: Addition is commutative, which means that `add(a, b) is the same as `add(b, a)\`.
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:126:1
+  --> $DIR/unescaped_backticks.rs:127:1
    |
 LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`."]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -703,7 +703,7 @@ LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same
            to this: Addition is commutative, which means that `add(a, b)` is the same as add(b, a)\`.
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:130:1
+  --> $DIR/unescaped_backticks.rs:131:1
    |
 LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)."]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -716,7 +716,7 @@ LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same
            to this: Addition is commutative, which means that `add(a, b)` is the same as \`add(b, a).
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:135:5
+  --> $DIR/unescaped_backticks.rs:136:5
    |
 LL | /// `foo
    |     ^
@@ -731,7 +731,7 @@ LL | /// \`foo
    |     +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:139:7
+  --> $DIR/unescaped_backticks.rs:140:7
    |
 LL | /// # `(heading
    |       ^
@@ -746,7 +746,7 @@ LL | /// # \`(heading
    |       +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:141:17
+  --> $DIR/unescaped_backticks.rs:142:17
    |
 LL | /// ## heading2)`
    |                 ^
@@ -761,7 +761,7 @@ LL | /// ## heading2)\`
    |                 +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:144:11
+  --> $DIR/unescaped_backticks.rs:145:11
    |
 LL | /// multi `(
    |           ^
@@ -776,7 +776,7 @@ LL | /// multi \`(
    |           +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:150:10
+  --> $DIR/unescaped_backticks.rs:151:10
    |
 LL | /// para)`(graph
    |          ^
@@ -795,7 +795,7 @@ LL | /// para)\`(graph
    |          +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:153:10
+  --> $DIR/unescaped_backticks.rs:154:10
    |
 LL | /// para)`(graph2
    |          ^
@@ -814,7 +814,7 @@ LL | /// para)\`(graph2
    |          +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:156:12
+  --> $DIR/unescaped_backticks.rs:157:12
    |
 LL | /// 1. foo)`
    |            ^
@@ -829,7 +829,7 @@ LL | /// 1. foo)\`
    |            +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:158:8
+  --> $DIR/unescaped_backticks.rs:159:8
    |
 LL | /// 2. `(bar
    |        ^
@@ -844,7 +844,7 @@ LL | /// 2. \`(bar
    |        +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:160:11
+  --> $DIR/unescaped_backticks.rs:161:11
    |
 LL | /// * baz)`
    |           ^
@@ -859,7 +859,7 @@ LL | /// * baz)\`
    |           +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:162:7
+  --> $DIR/unescaped_backticks.rs:163:7
    |
 LL | /// * `(quux
    |       ^
@@ -874,7 +874,7 @@ LL | /// * \`(quux
    |       +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:165:5
+  --> $DIR/unescaped_backticks.rs:166:5
    |
 LL | /// `#![this_is_actually_an_image(and(not), an = "attribute")]
    |     ^
@@ -889,7 +889,7 @@ LL | /// \`#![this_is_actually_an_image(and(not), an = "attribute")]
    |     +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:168:62
+  --> $DIR/unescaped_backticks.rs:169:62
    |
 LL | /// #![this_is_actually_an_image(and(not), an = "attribute")]`
    |                                                              ^
@@ -904,7 +904,7 @@ LL | /// #![this_is_actually_an_image(and(not), an = "attribute")]\`
    |                                                              +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:173:7
+  --> $DIR/unescaped_backticks.rs:174:7
    |
 LL | /// | `table( | )head` |
    |       ^
@@ -919,7 +919,7 @@ LL | /// | \`table( | )head` |
    |       +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:173:22
+  --> $DIR/unescaped_backticks.rs:174:22
    |
 LL | /// | `table( | )head` |
    |                      ^
@@ -934,7 +934,7 @@ LL | /// | `table( | )head\` |
    |                      +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:177:12
+  --> $DIR/unescaped_backticks.rs:178:12
    |
 LL | /// | table`( | )`body |
    |            ^
@@ -949,7 +949,7 @@ LL | /// | table\`( | )`body |
    |            +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:177:18
+  --> $DIR/unescaped_backticks.rs:178:18
    |
 LL | /// | table`( | )`body |
    |                  ^
diff --git a/tests/rustdoc/description.rs b/tests/rustdoc/description.rs
index 43cd59ebd09..aabbb4c4c8f 100644
--- a/tests/rustdoc/description.rs
+++ b/tests/rustdoc/description.rs
@@ -1,4 +1,5 @@
 #![crate_name = "foo"]
+#![allow(rustdoc::redundant_explicit_links)]
 //! # Description test crate
 //!
 //! This is the contents of the test crate docstring.
diff --git a/tests/rustdoc/intra-doc/basic.rs b/tests/rustdoc/intra-doc/basic.rs
index 96e21137b2d..c88a7887f11 100644
--- a/tests/rustdoc/intra-doc/basic.rs
+++ b/tests/rustdoc/intra-doc/basic.rs
@@ -1,3 +1,5 @@
+#![allow(rustdoc::redundant_explicit_links)]
+
 // @has basic/index.html
 // @has - '//a/@href' 'struct.ThisType.html'
 // @has - '//a/@title' 'struct basic::ThisType'
diff --git a/tests/rustdoc/intra-doc/generic-params.rs b/tests/rustdoc/intra-doc/generic-params.rs
index fbc9fc6a9bc..359f775f97f 100644
--- a/tests/rustdoc/intra-doc/generic-params.rs
+++ b/tests/rustdoc/intra-doc/generic-params.rs
@@ -1,6 +1,7 @@
 // ignore-tidy-linelength
 
 #![crate_name = "foo"]
+#![allow(rustdoc::redundant_explicit_links)]
 
 //! Here's a link to [`Vec<T>`] and one to [`Box<Vec<Option<T>>>`].
 //! Here's a link to [`Iterator<Box<T>>::Item`].
diff --git a/tests/rustdoc/intra-doc/issue-108459.rs b/tests/rustdoc/intra-doc/issue-108459.rs
index eb1c7a05e54..b8cd478b4df 100644
--- a/tests/rustdoc/intra-doc/issue-108459.rs
+++ b/tests/rustdoc/intra-doc/issue-108459.rs
@@ -1,4 +1,5 @@
 #![deny(rustdoc::broken_intra_doc_links)]
+#![allow(rustdoc::redundant_explicit_links)]
 
 pub struct S;
 pub mod char {}
diff --git a/tests/ui/abi/relocation_model_pic.rs b/tests/ui/abi/relocation_model_pic.rs
new file mode 100644
index 00000000000..0cfc44cd09d
--- /dev/null
+++ b/tests/ui/abi/relocation_model_pic.rs
@@ -0,0 +1,9 @@
+// run-pass
+// compile-flags: -C relocation-model=pic
+// ignore-emscripten no pic
+// ignore-wasm
+
+#![feature(cfg_relocation_model)]
+
+#[cfg(relocation_model = "pic")]
+fn main() {}
diff --git a/tests/ui/argument-suggestions/extra_arguments.rs b/tests/ui/argument-suggestions/extra_arguments.rs
index 1442062326d..4f2f3517ddd 100644
--- a/tests/ui/argument-suggestions/extra_arguments.rs
+++ b/tests/ui/argument-suggestions/extra_arguments.rs
@@ -1,12 +1,18 @@
 fn empty() {}
-fn one_arg(_a: i32) {}
+fn one_arg<T>(_a: T) {}
 fn two_arg_same(_a: i32, _b: i32) {}
 fn two_arg_diff(_a: i32, _b: &str) {}
 
 macro_rules! foo {
-    ($x:expr) => {
+    ($x:expr, ~) => {
         empty($x, 1); //~ ERROR function takes
-    }
+    };
+    ($x:expr, $y:expr) => {
+        empty($x, $y); //~ ERROR function takes
+    };
+    (~, $y:expr) => {
+        empty(1, $y); //~ ERROR function takes
+    };
 }
 
 fn main() {
@@ -39,5 +45,17 @@ fn main() {
     1,
     ""
   );
-  foo!(1);
+
+  // Check with macro expansions
+  foo!(1, ~);
+  foo!(~, 1);
+  foo!(1, 1);
+  one_arg(1, panic!()); //~ ERROR function takes
+  one_arg(panic!(), 1); //~ ERROR function takes
+  one_arg(stringify!($e), 1); //~ ERROR function takes
+
+  // Not a macro, but this also has multiple spans with equal source code,
+  // but different expansion contexts.
+  // https://github.com/rust-lang/rust/issues/114255
+  one_arg(for _ in 1.. {}, 1); //~ ERROR function takes
 }
diff --git a/tests/ui/argument-suggestions/extra_arguments.stderr b/tests/ui/argument-suggestions/extra_arguments.stderr
index 11c71099743..5ad8e35920a 100644
--- a/tests/ui/argument-suggestions/extra_arguments.stderr
+++ b/tests/ui/argument-suggestions/extra_arguments.stderr
@@ -1,5 +1,5 @@
 error[E0061]: this function takes 0 arguments but 1 argument was supplied
-  --> $DIR/extra_arguments.rs:13:3
+  --> $DIR/extra_arguments.rs:19:3
    |
 LL |   empty("");
    |   ^^^^^ --
@@ -14,7 +14,7 @@ LL | fn empty() {}
    |    ^^^^^
 
 error[E0061]: this function takes 0 arguments but 2 arguments were supplied
-  --> $DIR/extra_arguments.rs:14:3
+  --> $DIR/extra_arguments.rs:20:3
    |
 LL |   empty(1, 1);
    |   ^^^^^ -  - unexpected argument of type `{integer}`
@@ -33,7 +33,7 @@ LL +   empty();
    |
 
 error[E0061]: this function takes 1 argument but 2 arguments were supplied
-  --> $DIR/extra_arguments.rs:16:3
+  --> $DIR/extra_arguments.rs:22:3
    |
 LL |   one_arg(1, 1);
    |   ^^^^^^^  ---
@@ -44,11 +44,11 @@ LL |   one_arg(1, 1);
 note: function defined here
   --> $DIR/extra_arguments.rs:2:4
    |
-LL | fn one_arg(_a: i32) {}
-   |    ^^^^^^^ -------
+LL | fn one_arg<T>(_a: T) {}
+   |    ^^^^^^^    -----
 
 error[E0061]: this function takes 1 argument but 2 arguments were supplied
-  --> $DIR/extra_arguments.rs:17:3
+  --> $DIR/extra_arguments.rs:23:3
    |
 LL |   one_arg(1, "");
    |   ^^^^^^^  ----
@@ -59,11 +59,11 @@ LL |   one_arg(1, "");
 note: function defined here
   --> $DIR/extra_arguments.rs:2:4
    |
-LL | fn one_arg(_a: i32) {}
-   |    ^^^^^^^ -------
+LL | fn one_arg<T>(_a: T) {}
+   |    ^^^^^^^    -----
 
 error[E0061]: this function takes 1 argument but 3 arguments were supplied
-  --> $DIR/extra_arguments.rs:18:3
+  --> $DIR/extra_arguments.rs:24:3
    |
 LL |   one_arg(1, "", 1.0);
    |   ^^^^^^^    --  --- unexpected argument of type `{float}`
@@ -73,8 +73,8 @@ LL |   one_arg(1, "", 1.0);
 note: function defined here
   --> $DIR/extra_arguments.rs:2:4
    |
-LL | fn one_arg(_a: i32) {}
-   |    ^^^^^^^ -------
+LL | fn one_arg<T>(_a: T) {}
+   |    ^^^^^^^    -----
 help: remove the extra arguments
    |
 LL -   one_arg(1, "", 1.0);
@@ -82,7 +82,7 @@ LL +   one_arg(1);
    |
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
-  --> $DIR/extra_arguments.rs:20:3
+  --> $DIR/extra_arguments.rs:26:3
    |
 LL |   two_arg_same(1, 1, 1);
    |   ^^^^^^^^^^^^     ---
@@ -97,7 +97,7 @@ LL | fn two_arg_same(_a: i32, _b: i32) {}
    |    ^^^^^^^^^^^^ -------  -------
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
-  --> $DIR/extra_arguments.rs:21:3
+  --> $DIR/extra_arguments.rs:27:3
    |
 LL |   two_arg_same(1, 1, 1.0);
    |   ^^^^^^^^^^^^     -----
@@ -112,7 +112,7 @@ LL | fn two_arg_same(_a: i32, _b: i32) {}
    |    ^^^^^^^^^^^^ -------  -------
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
-  --> $DIR/extra_arguments.rs:23:3
+  --> $DIR/extra_arguments.rs:29:3
    |
 LL |   two_arg_diff(1, 1, "");
    |   ^^^^^^^^^^^^  ---
@@ -127,7 +127,7 @@ LL | fn two_arg_diff(_a: i32, _b: &str) {}
    |    ^^^^^^^^^^^^ -------  --------
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
-  --> $DIR/extra_arguments.rs:24:3
+  --> $DIR/extra_arguments.rs:30:3
    |
 LL |   two_arg_diff(1, "", "");
    |   ^^^^^^^^^^^^      ----
@@ -142,7 +142,7 @@ LL | fn two_arg_diff(_a: i32, _b: &str) {}
    |    ^^^^^^^^^^^^ -------  --------
 
 error[E0061]: this function takes 2 arguments but 4 arguments were supplied
-  --> $DIR/extra_arguments.rs:25:3
+  --> $DIR/extra_arguments.rs:31:3
    |
 LL |   two_arg_diff(1, 1, "", "");
    |   ^^^^^^^^^^^^    -      -- unexpected argument of type `&'static str`
@@ -161,7 +161,7 @@ LL +   two_arg_diff(1, "");
    |
 
 error[E0061]: this function takes 2 arguments but 4 arguments were supplied
-  --> $DIR/extra_arguments.rs:26:3
+  --> $DIR/extra_arguments.rs:32:3
    |
 LL |   two_arg_diff(1, "", 1, "");
    |   ^^^^^^^^^^^^        -  -- unexpected argument of type `&'static str`
@@ -180,7 +180,7 @@ LL +   two_arg_diff(1, "");
    |
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
-  --> $DIR/extra_arguments.rs:29:3
+  --> $DIR/extra_arguments.rs:35:3
    |
 LL |   two_arg_same(1, 1,     "");
    |   ^^^^^^^^^^^^     --------
@@ -195,7 +195,7 @@ LL | fn two_arg_same(_a: i32, _b: i32) {}
    |    ^^^^^^^^^^^^ -------  -------
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
-  --> $DIR/extra_arguments.rs:30:3
+  --> $DIR/extra_arguments.rs:36:3
    |
 LL |   two_arg_diff(1, 1,     "");
    |   ^^^^^^^^^^^^  ---
@@ -210,7 +210,7 @@ LL | fn two_arg_diff(_a: i32, _b: &str) {}
    |    ^^^^^^^^^^^^ -------  --------
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
-  --> $DIR/extra_arguments.rs:31:3
+  --> $DIR/extra_arguments.rs:37:3
    |
 LL |     two_arg_same(
    |     ^^^^^^^^^^^^
@@ -230,7 +230,7 @@ LL | fn two_arg_same(_a: i32, _b: i32) {}
    |    ^^^^^^^^^^^^ -------  -------
 
 error[E0061]: this function takes 2 arguments but 3 arguments were supplied
-  --> $DIR/extra_arguments.rs:37:3
+  --> $DIR/extra_arguments.rs:43:3
    |
 LL |     two_arg_diff(
    |     ^^^^^^^^^^^^
@@ -254,11 +254,10 @@ error[E0061]: this function takes 0 arguments but 2 arguments were supplied
 LL |         empty($x, 1);
    |         ^^^^^     - unexpected argument of type `{integer}`
 ...
-LL |   foo!(1);
-   |   -------
+LL |   foo!(1, ~);
+   |   ----------
    |   |    |
    |   |    unexpected argument of type `{integer}`
-   |   |    help: remove the extra argument
    |   in this macro invocation
    |
 note: function defined here
@@ -268,6 +267,105 @@ LL | fn empty() {}
    |    ^^^^^
    = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 16 previous errors
+error[E0061]: this function takes 0 arguments but 2 arguments were supplied
+  --> $DIR/extra_arguments.rs:14:9
+   |
+LL |         empty(1, $y);
+   |         ^^^^^ - unexpected argument of type `{integer}`
+...
+LL |   foo!(~, 1);
+   |   ----------
+   |   |       |
+   |   |       unexpected argument of type `{integer}`
+   |   in this macro invocation
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:1:4
+   |
+LL | fn empty() {}
+   |    ^^^^^
+   = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0061]: this function takes 0 arguments but 2 arguments were supplied
+  --> $DIR/extra_arguments.rs:11:9
+   |
+LL |         empty($x, $y);
+   |         ^^^^^
+...
+LL |   foo!(1, 1);
+   |   ----------
+   |   |    |  |
+   |   |    |  unexpected argument of type `{integer}`
+   |   |    unexpected argument of type `{integer}`
+   |   in this macro invocation
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:1:4
+   |
+LL | fn empty() {}
+   |    ^^^^^
+   = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0061]: this function takes 1 argument but 2 arguments were supplied
+  --> $DIR/extra_arguments.rs:53:3
+   |
+LL |   one_arg(1, panic!());
+   |   ^^^^^^^  ----------
+   |            | |
+   |            | unexpected argument
+   |            help: remove the extra argument
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:2:4
+   |
+LL | fn one_arg<T>(_a: T) {}
+   |    ^^^^^^^    -----
+
+error[E0061]: this function takes 1 argument but 2 arguments were supplied
+  --> $DIR/extra_arguments.rs:54:3
+   |
+LL |   one_arg(panic!(), 1);
+   |   ^^^^^^^         ---
+   |                   | |
+   |                   | unexpected argument of type `{integer}`
+   |                   help: remove the extra argument
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:2:4
+   |
+LL | fn one_arg<T>(_a: T) {}
+   |    ^^^^^^^    -----
+
+error[E0061]: this function takes 1 argument but 2 arguments were supplied
+  --> $DIR/extra_arguments.rs:55:3
+   |
+LL |   one_arg(stringify!($e), 1);
+   |   ^^^^^^^               ---
+   |                         | |
+   |                         | unexpected argument of type `{integer}`
+   |                         help: remove the extra argument
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:2:4
+   |
+LL | fn one_arg<T>(_a: T) {}
+   |    ^^^^^^^    -----
+
+error[E0061]: this function takes 1 argument but 2 arguments were supplied
+  --> $DIR/extra_arguments.rs:60:3
+   |
+LL |   one_arg(for _ in 1.. {}, 1);
+   |   ^^^^^^^                ---
+   |                          | |
+   |                          | unexpected argument of type `{integer}`
+   |                          help: remove the extra argument
+   |
+note: function defined here
+  --> $DIR/extra_arguments.rs:2:4
+   |
+LL | fn one_arg<T>(_a: T) {}
+   |    ^^^^^^^    -----
+
+error: aborting due to 22 previous errors
 
 For more information about this error, try `rustc --explain E0061`.
diff --git a/tests/ui/associated-type-bounds/consts.rs b/tests/ui/associated-type-bounds/consts.rs
new file mode 100644
index 00000000000..9b95b1b52c0
--- /dev/null
+++ b/tests/ui/associated-type-bounds/consts.rs
@@ -0,0 +1,10 @@
+#![feature(associated_type_bounds)]
+
+pub fn accept(_: impl Trait<K: Copy>) {}
+//~^ ERROR expected associated type, found associated constant
+
+pub trait Trait {
+    const K: i32;
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/consts.stderr b/tests/ui/associated-type-bounds/consts.stderr
new file mode 100644
index 00000000000..ddfb6612b08
--- /dev/null
+++ b/tests/ui/associated-type-bounds/consts.stderr
@@ -0,0 +1,10 @@
+error: expected associated type, found associated constant
+  --> $DIR/consts.rs:3:29
+   |
+LL | pub fn accept(_: impl Trait<K: Copy>) {}
+   |                             ^
+   |
+   = note: trait bounds not allowed on associated constant
+
+error: aborting due to previous error
+
diff --git a/tests/ui/associated-types/dont-suggest-cyclic-constraint.fixed b/tests/ui/associated-types/dont-suggest-cyclic-constraint.fixed
deleted file mode 100644
index ec4165cc71e..00000000000
--- a/tests/ui/associated-types/dont-suggest-cyclic-constraint.fixed
+++ /dev/null
@@ -1,13 +0,0 @@
-// run-rustfix
-
-use std::fmt::Debug;
-
-pub fn foo<I: Iterator>(mut iter: I, value: &I::Item)
-where
-    I::Item: Eq + Debug,
-{
-    debug_assert_eq!(iter.next().as_ref(), Some(value));
-    //~^ ERROR mismatched types
-}
-
-fn main() {}
diff --git a/tests/ui/associated-types/dont-suggest-cyclic-constraint.rs b/tests/ui/associated-types/dont-suggest-cyclic-constraint.rs
index 0b4df08783d..0848b4c559b 100644
--- a/tests/ui/associated-types/dont-suggest-cyclic-constraint.rs
+++ b/tests/ui/associated-types/dont-suggest-cyclic-constraint.rs
@@ -1,5 +1,3 @@
-// run-rustfix
-
 use std::fmt::Debug;
 
 pub fn foo<I: Iterator>(mut iter: I, value: &I::Item)
diff --git a/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr b/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr
index 65d18761b18..3ecac9c83e5 100644
--- a/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr
+++ b/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr
@@ -1,15 +1,11 @@
 error[E0308]: mismatched types
-  --> $DIR/dont-suggest-cyclic-constraint.rs:9:35
+  --> $DIR/dont-suggest-cyclic-constraint.rs:7:35
    |
 LL |     debug_assert_eq!(iter.next(), Some(value));
    |                                   ^^^^^^^^^^^ expected `Option<<I as Iterator>::Item>`, found `Option<&<I as Iterator>::Item>`
    |
    = note: expected enum `Option<<I as Iterator>::Item>`
               found enum `Option<&<I as Iterator>::Item>`
-help: use `Option::as_ref` to convert `Option<<I as Iterator>::Item>` to `Option<&<I as Iterator>::Item>`
-   |
-LL |     debug_assert_eq!(iter.next().as_ref(), Some(value));
-   |                                 +++++++++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/async-await/deep-futures-are-freeze.rs b/tests/ui/async-await/deep-futures-are-freeze.rs
new file mode 100644
index 00000000000..dd676d5e18c
--- /dev/null
+++ b/tests/ui/async-await/deep-futures-are-freeze.rs
@@ -0,0 +1,179 @@
+// build-pass
+// compile-flags: -Copt-level=s -Clto=fat
+// no-prefer-dynamic
+// edition: 2021
+
+#![recursion_limit = "256"]
+
+fn main() {
+    spawn(move || main0())
+}
+
+fn spawn<F>(future: impl FnOnce() -> F) {
+    future();
+}
+
+async fn main0() {
+    main1().await;
+    main2().await;
+}
+async fn main1() {
+    main2().await;
+    main3().await;
+}
+async fn main2() {
+    main3().await;
+    main4().await;
+}
+async fn main3() {
+    main4().await;
+    main5().await;
+}
+async fn main4() {
+    main5().await;
+    main6().await;
+}
+async fn main5() {
+    main6().await;
+    main7().await;
+}
+async fn main6() {
+    main7().await;
+    main8().await;
+}
+async fn main7() {
+    main8().await;
+    main9().await;
+}
+async fn main8() {
+    main9().await;
+    main10().await;
+}
+async fn main9() {
+    main10().await;
+    main11().await;
+}
+async fn main10() {
+    main11().await;
+    main12().await;
+}
+async fn main11() {
+    main12().await;
+    main13().await;
+}
+async fn main12() {
+    main13().await;
+    main14().await;
+}
+async fn main13() {
+    main14().await;
+    main15().await;
+}
+async fn main14() {
+    main15().await;
+    main16().await;
+}
+async fn main15() {
+    main16().await;
+    main17().await;
+}
+async fn main16() {
+    main17().await;
+    main18().await;
+}
+async fn main17() {
+    main18().await;
+    main19().await;
+}
+async fn main18() {
+    main19().await;
+    main20().await;
+}
+async fn main19() {
+    main20().await;
+    main21().await;
+}
+async fn main20() {
+    main21().await;
+    main22().await;
+}
+async fn main21() {
+    main22().await;
+    main23().await;
+}
+async fn main22() {
+    main23().await;
+    main24().await;
+}
+async fn main23() {
+    main24().await;
+    main25().await;
+}
+async fn main24() {
+    main25().await;
+    main26().await;
+}
+async fn main25() {
+    main26().await;
+    main27().await;
+}
+async fn main26() {
+    main27().await;
+    main28().await;
+}
+async fn main27() {
+    main28().await;
+    main29().await;
+}
+async fn main28() {
+    main29().await;
+    main30().await;
+}
+async fn main29() {
+    main30().await;
+    main31().await;
+}
+async fn main30() {
+    main31().await;
+    main32().await;
+}
+async fn main31() {
+    main32().await;
+    main33().await;
+}
+async fn main32() {
+    main33().await;
+    main34().await;
+}
+async fn main33() {
+    main34().await;
+    main35().await;
+}
+async fn main34() {
+    main35().await;
+    main36().await;
+}
+async fn main35() {
+    main36().await;
+    main37().await;
+}
+async fn main36() {
+    main37().await;
+    main38().await;
+}
+async fn main37() {
+    main38().await;
+    main39().await;
+}
+async fn main38() {
+    main39().await;
+    main40().await;
+}
+async fn main39() {
+    main40().await;
+}
+async fn main40() {
+    boom(&mut ()).await;
+}
+
+async fn boom(f: &mut ()) {}
diff --git a/tests/ui/async-await/normalize-output-in-signature-deduction.rs b/tests/ui/async-await/normalize-output-in-signature-deduction.rs
new file mode 100644
index 00000000000..960065a83a4
--- /dev/null
+++ b/tests/ui/async-await/normalize-output-in-signature-deduction.rs
@@ -0,0 +1,19 @@
+// edition:2021
+// revisions: current next
+//[next] compile-flags: -Ztrait-solver=next
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+struct Foo;
+
+impl Trait for Foo {}
+pub trait Trait {}
+
+pub type TAIT<T> = impl Trait;
+
+async fn foo<T>() -> TAIT<T> {
+    Foo
+}
+
+fn main() {}
diff --git a/tests/ui/consts/assert-type-intrinsics.stderr b/tests/ui/consts/assert-type-intrinsics.stderr
index 70aec91e226..3c03b03deee 100644
--- a/tests/ui/consts/assert-type-intrinsics.stderr
+++ b/tests/ui/consts/assert-type-intrinsics.stderr
@@ -2,19 +2,19 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/assert-type-intrinsics.rs:12:9
    |
 LL |         MaybeUninit::<!>::uninit().assume_init();
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to instantiate uninhabited type `!`', $DIR/assert-type-intrinsics.rs:12:36
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/assert-type-intrinsics.rs:16:9
    |
 LL |         intrinsics::assert_mem_uninitialized_valid::<&'static i32>();
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to leave type `&i32` uninitialized, which is invalid
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to leave type `&i32` uninitialized, which is invalid', $DIR/assert-type-intrinsics.rs:16:9
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/assert-type-intrinsics.rs:20:9
    |
 LL |         intrinsics::assert_zero_valid::<&'static i32>();
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `&i32`, which is invalid
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to zero-initialize type `&i32`, which is invalid', $DIR/assert-type-intrinsics.rs:20:9
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-cfg-relocation-model.rs b/tests/ui/feature-gates/feature-gate-cfg-relocation-model.rs
new file mode 100644
index 00000000000..7529014ece2
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-cfg-relocation-model.rs
@@ -0,0 +1,4 @@
+#[cfg(relocation_model = "pic")] //~ ERROR
+fn _foo() {}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-cfg-relocation-model.stderr b/tests/ui/feature-gates/feature-gate-cfg-relocation-model.stderr
new file mode 100644
index 00000000000..592768a4203
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-cfg-relocation-model.stderr
@@ -0,0 +1,12 @@
+error[E0658]: `cfg(relocation_model)` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-relocation-model.rs:1:7
+   |
+LL | #[cfg(relocation_model = "pic")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #114929 <https://github.com/rust-lang/rust/issues/114929> for more information
+   = help: add `#![feature(cfg_relocation_model)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/inference/str-as-char.fixed b/tests/ui/inference/str-as-char.fixed
index 6aea809cbdb..911b067c4d1 100644
--- a/tests/ui/inference/str-as-char.fixed
+++ b/tests/ui/inference/str-as-char.fixed
@@ -7,4 +7,5 @@ fn main() {
     let _: &str = "a";   //~ ERROR mismatched types
     let _: &str = "\"\"\""; //~ ERROR character literal may only contain one codepoint
     let _: &str = "\"\"\""; //~ ERROR character literal may only contain one codepoint
+    let _: &str = "\"\"\\\"\\\"\\\\\""; //~ ERROR character literal may only contain one codepoint
 }
diff --git a/tests/ui/inference/str-as-char.rs b/tests/ui/inference/str-as-char.rs
index eaa8d788c34..832bc871a9e 100644
--- a/tests/ui/inference/str-as-char.rs
+++ b/tests/ui/inference/str-as-char.rs
@@ -7,4 +7,5 @@ fn main() {
     let _: &str = 'a';   //~ ERROR mismatched types
     let _: &str = '"""'; //~ ERROR character literal may only contain one codepoint
     let _: &str = '\"\"\"'; //~ ERROR character literal may only contain one codepoint
+    let _: &str = '"\"\\"\\\"\\\\"'; //~ ERROR character literal may only contain one codepoint
 }
diff --git a/tests/ui/inference/str-as-char.stderr b/tests/ui/inference/str-as-char.stderr
index 2c84dac8e0c..216f4cda698 100644
--- a/tests/ui/inference/str-as-char.stderr
+++ b/tests/ui/inference/str-as-char.stderr
@@ -20,6 +20,17 @@ help: if you meant to write a `str` literal, use double quotes
 LL |     let _: &str = "\"\"\"";
    |                   ~~~~~~~~
 
+error: character literal may only contain one codepoint
+  --> $DIR/str-as-char.rs:10:19
+   |
+LL |     let _: &str = '"\"\"\\"\\"';
+   |                   ^^^^^^^^^^^^^^^^^
+   |
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL |     let _: &str = "\"\"\\"\\"\\\"";
+   |                   ~~~~~~~~~~~~~~~~~~~~
+
 error[E0308]: mismatched types
   --> $DIR/str-as-char.rs:7:19
    |
@@ -33,6 +44,6 @@ help: if you meant to write a `str` literal, use double quotes
 LL |     let _: &str = "a";
    |                   ~~~
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/inline-const/required-const.rs b/tests/ui/inline-const/required-const.rs
new file mode 100644
index 00000000000..0483410662b
--- /dev/null
+++ b/tests/ui/inline-const/required-const.rs
@@ -0,0 +1,13 @@
+// build-fail
+// compile-flags: -Zmir-opt-level=3
+#![feature(inline_const)]
+
+fn foo<T>() {
+    if false {
+        const { panic!() } //~ ERROR E0080
+    }
+}
+
+fn main() {
+    foo::<i32>();
+}
diff --git a/tests/ui/inline-const/required-const.stderr b/tests/ui/inline-const/required-const.stderr
new file mode 100644
index 00000000000..d6948e7acc0
--- /dev/null
+++ b/tests/ui/inline-const/required-const.stderr
@@ -0,0 +1,11 @@
+error[E0080]: evaluation of `foo::<i32>::{constant#0}` failed
+  --> $DIR/required-const.rs:7:17
+   |
+LL |         const { panic!() }
+   |                 ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/required-const.rs:7:17
+   |
+   = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/issues/issue-48364.stderr b/tests/ui/issues/issue-48364.stderr
index cac4af6a7f3..3f2e1b83ad5 100644
--- a/tests/ui/issues/issue-48364.stderr
+++ b/tests/ui/issues/issue-48364.stderr
@@ -10,7 +10,6 @@ LL |     b"".starts_with(stringify!(foo))
               found reference `&'static str`
 note: method defined here
   --> $SRC_DIR/core/src/slice/mod.rs:LL:COL
-   = note: this error originates in the macro `stringify` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
diff --git a/tests/ui/lint/reference_casting.rs b/tests/ui/lint/reference_casting.rs
index f4e463b67c0..6c38bca3daa 100644
--- a/tests/ui/lint/reference_casting.rs
+++ b/tests/ui/lint/reference_casting.rs
@@ -9,6 +9,10 @@ extern "C" {
     fn int_ffi(c: *mut i32);
 }
 
+fn static_u8() -> &'static u8 {
+    &8
+}
+
 unsafe fn ref_to_mut() {
     let num = &3i32;
 
@@ -24,12 +28,28 @@ unsafe fn ref_to_mut() {
     //~^ ERROR casting `&T` to `&mut T` is undefined behavior
     let _num = &mut *(std::ptr::from_ref({ num }) as *mut i32);
     //~^ ERROR casting `&T` to `&mut T` is undefined behavior
+    let _num = &mut *(num as *const i32).cast::<i32>().cast_mut();
+    //~^ ERROR casting `&T` to `&mut T` is undefined behavior
+    let _num = &mut *(num as *const i32).cast::<i32>().cast_mut().cast_const().cast_mut();
+    //~^ ERROR casting `&T` to `&mut T` is undefined behavior
+    let _num = &mut *(std::ptr::from_ref(static_u8()) as *mut i32);
+    //~^ ERROR casting `&T` to `&mut T` is undefined behavior
     let _num = &mut *std::mem::transmute::<_, *mut i32>(num);
     //~^ ERROR casting `&T` to `&mut T` is undefined behavior
 
     let deferred = num as *const i32 as *mut i32;
     let _num = &mut *deferred;
     //~^ ERROR casting `&T` to `&mut T` is undefined behavior
+    let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).cast_mut() as *mut i32;
+    let _num = &mut *deferred;
+    //~^ ERROR casting `&T` to `&mut T` is undefined behavior
+    let _num = &mut *(num as *const _ as usize as *mut i32);
+    //~^ ERROR casting `&T` to `&mut T` is undefined behavior
+
+    unsafe fn generic_ref_cast_mut<T>(this: &T) -> &mut T {
+        &mut *((this as *const _) as *mut _)
+        //~^ ERROR casting `&T` to `&mut T` is undefined behavior
+    }
 }
 
 unsafe fn assign_to_ref() {
@@ -55,6 +75,15 @@ unsafe fn assign_to_ref() {
     let value = num as *const i32 as *mut i32;
     *value = 1;
     //~^ ERROR assigning to `&T` is undefined behavior
+    *(num as *const i32).cast::<i32>().cast_mut() = 2;
+    //~^ ERROR assigning to `&T` is undefined behavior
+    *(num as *const _ as usize as *mut i32) = 2;
+    //~^ ERROR assigning to `&T` is undefined behavior
+
+    unsafe fn generic_assign_to_ref<T>(this: &T, a: T) {
+        *(this as *const _ as *mut _) = a;
+        //~^ ERROR assigning to `&T` is undefined behavior
+    }
 }
 
 unsafe fn no_warn() {
diff --git a/tests/ui/lint/reference_casting.stderr b/tests/ui/lint/reference_casting.stderr
index e8bb0557ca8..7ff9b76a85e 100644
--- a/tests/ui/lint/reference_casting.stderr
+++ b/tests/ui/lint/reference_casting.stderr
@@ -1,5 +1,5 @@
 error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:15:16
+  --> $DIR/reference_casting.rs:19:16
    |
 LL |     let _num = &mut *(num as *const i32 as *mut i32);
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,98 +7,154 @@ LL |     let _num = &mut *(num as *const i32 as *mut i32);
    = note: `#[deny(invalid_reference_casting)]` on by default
 
 error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:17:16
+  --> $DIR/reference_casting.rs:21:16
    |
 LL |     let _num = &mut *(num as *const i32).cast_mut();
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:19:16
+  --> $DIR/reference_casting.rs:23:16
    |
 LL |     let _num = &mut *std::ptr::from_ref(num).cast_mut();
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:21:16
+  --> $DIR/reference_casting.rs:25:16
    |
 LL |     let _num = &mut *std::ptr::from_ref({ num }).cast_mut();
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:23:16
+  --> $DIR/reference_casting.rs:27:16
    |
 LL |     let _num = &mut *{ std::ptr::from_ref(num) }.cast_mut();
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:25:16
+  --> $DIR/reference_casting.rs:29:16
    |
 LL |     let _num = &mut *(std::ptr::from_ref({ num }) as *mut i32);
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:27:16
+  --> $DIR/reference_casting.rs:31:16
+   |
+LL |     let _num = &mut *(num as *const i32).cast::<i32>().cast_mut();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
+  --> $DIR/reference_casting.rs:33:16
+   |
+LL |     let _num = &mut *(num as *const i32).cast::<i32>().cast_mut().cast_const().cast_mut();
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
+  --> $DIR/reference_casting.rs:35:16
+   |
+LL |     let _num = &mut *(std::ptr::from_ref(static_u8()) as *mut i32);
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
+  --> $DIR/reference_casting.rs:37:16
    |
 LL |     let _num = &mut *std::mem::transmute::<_, *mut i32>(num);
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:31:16
+  --> $DIR/reference_casting.rs:41:16
    |
 LL |     let deferred = num as *const i32 as *mut i32;
    |                    ----------------------------- casting happend here
 LL |     let _num = &mut *deferred;
    |                ^^^^^^^^^^^^^^
 
+error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
+  --> $DIR/reference_casting.rs:44:16
+   |
+LL |     let deferred = (std::ptr::from_ref(num) as *const i32 as *const i32).cast_mut() as *mut i32;
+   |                    ---------------------------------------------------------------------------- casting happend here
+LL |     let _num = &mut *deferred;
+   |                ^^^^^^^^^^^^^^
+
+error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
+  --> $DIR/reference_casting.rs:46:16
+   |
+LL |     let _num = &mut *(num as *const _ as usize as *mut i32);
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`
+  --> $DIR/reference_casting.rs:50:9
+   |
+LL |         &mut *((this as *const _) as *mut _)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:40:5
+  --> $DIR/reference_casting.rs:60:5
    |
 LL |     *(a as *const _ as *mut _) = String::from("Replaced");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:42:5
+  --> $DIR/reference_casting.rs:62:5
    |
 LL |     *(a as *const _ as *mut String) += " world";
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:44:5
+  --> $DIR/reference_casting.rs:64:5
    |
 LL |     *std::ptr::from_ref(num).cast_mut() += 1;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:46:5
+  --> $DIR/reference_casting.rs:66:5
    |
 LL |     *std::ptr::from_ref({ num }).cast_mut() += 1;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:48:5
+  --> $DIR/reference_casting.rs:68:5
    |
 LL |     *{ std::ptr::from_ref(num) }.cast_mut() += 1;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:50:5
+  --> $DIR/reference_casting.rs:70:5
    |
 LL |     *(std::ptr::from_ref({ num }) as *mut i32) += 1;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:52:5
+  --> $DIR/reference_casting.rs:72:5
    |
 LL |     *std::mem::transmute::<_, *mut i32>(num) += 1;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
-  --> $DIR/reference_casting.rs:56:5
+  --> $DIR/reference_casting.rs:76:5
    |
 LL |     let value = num as *const i32 as *mut i32;
    |                 ----------------------------- casting happend here
 LL |     *value = 1;
    |     ^^^^^^^^^^
 
-error: aborting due to 16 previous errors
+error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
+  --> $DIR/reference_casting.rs:78:5
+   |
+LL |     *(num as *const i32).cast::<i32>().cast_mut() = 2;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
+  --> $DIR/reference_casting.rs:80:5
+   |
+LL |     *(num as *const _ as usize as *mut i32) = 2;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: assigning to `&T` is undefined behavior, consider using an `UnsafeCell`
+  --> $DIR/reference_casting.rs:84:9
+   |
+LL |         *(this as *const _ as *mut _) = a;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 25 previous errors
 
diff --git a/tests/ui/macros/macro-interpolation.rs b/tests/ui/macros/macro-interpolation.rs
index 35003a79ad7..48c1f19e777 100644
--- a/tests/ui/macros/macro-interpolation.rs
+++ b/tests/ui/macros/macro-interpolation.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 macro_rules! overly_complicated {
     ($fnname:ident, $arg:ident, $ty:ty, $body:block, $val:expr, $pat:pat, $res:path) =>
     ({
@@ -21,12 +19,14 @@ macro_rules! qpath {
 
     (ty, <$type:ty as $trait:ty>::$name:ident) => {
         <$type as $trait>::$name
+        //~^ ERROR expected identifier, found `!`
     };
 }
 
 pub fn main() {
     let _: qpath!(path, <str as ToOwned>::Owned);
     let _: qpath!(ty, <str as ToOwned>::Owned);
+    let _: qpath!(ty, <str as !>::Owned);
 
     assert!(overly_complicated!(f, x, Option<usize>, { return Some(x); },
                                Some(8), Some(y), y) == 8)
diff --git a/tests/ui/macros/macro-interpolation.stderr b/tests/ui/macros/macro-interpolation.stderr
new file mode 100644
index 00000000000..7ef1fcbbce3
--- /dev/null
+++ b/tests/ui/macros/macro-interpolation.stderr
@@ -0,0 +1,16 @@
+error: expected identifier, found `!`
+  --> $DIR/macro-interpolation.rs:21:19
+   |
+LL |         <$type as $trait>::$name
+   |                   ^^^^^^ expected identifier
+...
+LL |     let _: qpath!(ty, <str as !>::Owned);
+   |            -----------------------------
+   |            |
+   |            this macro call doesn't expand to a type
+   |            in this macro invocation
+   |
+   = note: this error originates in the macro `qpath` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.rs b/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.rs
new file mode 100644
index 00000000000..9cc572c23a1
--- /dev/null
+++ b/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.rs
@@ -0,0 +1,14 @@
+#![feature(macro_metavar_expr)]
+
+macro_rules! foo {
+    ( $( $($t:ident),* );* ) => { ${count(t,)} }
+    //~^ ERROR `count` followed by a comma must have an associated
+    //~| ERROR expected expression, found `$`
+}
+
+fn test() {
+    foo!(a, a; b, b);
+}
+
+fn main() {
+}
diff --git a/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.stderr b/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.stderr
new file mode 100644
index 00000000000..e9317a5c347
--- /dev/null
+++ b/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.stderr
@@ -0,0 +1,19 @@
+error: `count` followed by a comma must have an associated index indicating its depth
+  --> $DIR/issue-111904.rs:4:37
+   |
+LL |     ( $( $($t:ident),* );* ) => { ${count(t,)} }
+   |                                     ^^^^^
+
+error: expected expression, found `$`
+  --> $DIR/issue-111904.rs:4:35
+   |
+LL |     ( $( $($t:ident),* );* ) => { ${count(t,)} }
+   |                                   ^ expected expression
+...
+LL |     foo!(a, a; b, b);
+   |     ---------------- in this macro invocation
+   |
+   = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/match/issue-114691.rs b/tests/ui/match/issue-114691.rs
new file mode 100644
index 00000000000..cc17d9ecf05
--- /dev/null
+++ b/tests/ui/match/issue-114691.rs
@@ -0,0 +1,39 @@
+// run-pass
+
+// This test used to be miscompiled by LLVM 17.
+#![allow(dead_code)]
+
+enum Pass {
+    Opaque {
+        clear_color: [f32; 4],
+        with_depth_pre_pass: bool,
+    },
+    Transparent,
+}
+
+enum LoadOp {
+    Clear,
+    Load,
+}
+
+#[inline(never)]
+fn check(x: Option<LoadOp>) {
+    assert!(x.is_none());
+}
+
+#[inline(never)]
+fn test(mode: Pass) {
+    check(match mode {
+        Pass::Opaque {
+            with_depth_pre_pass: true,
+            ..
+        }
+        | Pass::Transparent => None,
+        _ => Some(LoadOp::Clear),
+    });
+}
+
+fn main() {
+    println!("Hello, world!");
+    test(Pass::Transparent);
+}
diff --git a/tests/ui/mir/debug-ref-undef.rs b/tests/ui/mir/debug-ref-undef.rs
new file mode 100644
index 00000000000..37fd22a9dd2
--- /dev/null
+++ b/tests/ui/mir/debug-ref-undef.rs
@@ -0,0 +1,57 @@
+// run-pass
+// compile-flags: -g -O -Zmir-opt-level=0 -Zinline-mir=y -Zmir-enable-passes=+ReferencePropagation
+
+#![allow(dead_code)]
+
+use std::marker::PhantomData;
+
+struct RawTable<T> {
+    marker: PhantomData<T>,
+}
+
+impl<T> RawTable<T> {
+    fn iter(&self) -> RawIter<T> {
+        RawIter { marker: PhantomData }
+    }
+}
+
+struct RawIter<T> {
+    marker: PhantomData<T>,
+}
+
+impl<T> Iterator for RawIter<T> {
+    type Item = ();
+    fn next(&mut self) -> Option<()> {
+        None
+    }
+}
+
+struct HashMap<T> {
+    table: RawTable<T>,
+}
+
+struct Iter<T> {
+    inner: RawIter<T>, // Removing this breaks the reproducer
+}
+
+impl<T> IntoIterator for &HashMap<T> {
+    type Item = T;
+    type IntoIter = Iter<T>;
+    fn into_iter(self) -> Iter<T> {
+        Iter { inner: self.table.iter() }
+    }
+}
+
+impl<T> Iterator for Iter<T> {
+    type Item = T;
+    fn next(&mut self) -> Option<T> {
+        None
+    }
+}
+
+pub fn main() {
+    let maybe_hash_set: Option<HashMap<()>> = None;
+    for _ in maybe_hash_set.as_ref().unwrap_or(&HashMap { table: RawTable { marker: PhantomData } })
+    {
+    }
+}
diff --git a/tests/ui/or-patterns/missing-bindings.stderr b/tests/ui/or-patterns/missing-bindings.stderr
index 8fafa275b5c..4457b7893d5 100644
--- a/tests/ui/or-patterns/missing-bindings.stderr
+++ b/tests/ui/or-patterns/missing-bindings.stderr
@@ -79,6 +79,14 @@ LL |     let (A(A(..) | B(a), _) | B(A(a, _) | B(a))) = Y;
    |            |
    |            pattern doesn't bind `a`
 
+error[E0408]: variable `c` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:45:12
+   |
+LL |     let (A(A(a, b) | B(c), d) | B(e)) = Y;
+   |            ^^^^^^^     - variable not in all patterns
+   |            |
+   |            pattern doesn't bind `c`
+
 error[E0408]: variable `a` is not bound in all patterns
   --> $DIR/missing-bindings.rs:45:22
    |
@@ -96,12 +104,12 @@ LL |     let (A(A(a, b) | B(c), d) | B(e)) = Y;
    |                 variable not in all patterns
 
 error[E0408]: variable `c` is not bound in all patterns
-  --> $DIR/missing-bindings.rs:45:12
+  --> $DIR/missing-bindings.rs:45:33
    |
 LL |     let (A(A(a, b) | B(c), d) | B(e)) = Y;
-   |            ^^^^^^^     - variable not in all patterns
-   |            |
-   |            pattern doesn't bind `c`
+   |                        -        ^^^^ pattern doesn't bind `c`
+   |                        |
+   |                        variable not in all patterns
 
 error[E0408]: variable `d` is not bound in all patterns
   --> $DIR/missing-bindings.rs:45:33
@@ -135,14 +143,6 @@ LL |     let (A(A(a, b) | B(c), d) | B(e)) = Y;
    |                 |
    |                 variable not in all patterns
 
-error[E0408]: variable `c` is not bound in all patterns
-  --> $DIR/missing-bindings.rs:45:33
-   |
-LL |     let (A(A(a, b) | B(c), d) | B(e)) = Y;
-   |                        -        ^^^^ pattern doesn't bind `c`
-   |                        |
-   |                        variable not in all patterns
-
 error[E0408]: variable `a` is not bound in all patterns
   --> $DIR/missing-bindings.rs:61:29
    |
@@ -185,6 +185,28 @@ LL |                     B(b),
 LL |                 B(_)
    |                 ^^^^ pattern doesn't bind `b`
 
+error[E0408]: variable `c` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:57:13
+   |
+LL | /             V1(
+LL | |
+LL | |
+LL | |                 A(
+...  |
+LL | |                 B(Ok(a) | Err(a))
+LL | |             ) |
+   | |_____________^ pattern doesn't bind `c`
+LL | /             V2(
+LL | |                 A(
+LL | |                     A(_, a) |
+LL | |                     B(b),
+...  |
+LL | |
+LL | |             ) |
+   | |_____________^ pattern doesn't bind `c`
+LL |               V3(c),
+   |                  - variable not in all patterns
+
 error[E0408]: variable `a` is not bound in all patterns
   --> $DIR/missing-bindings.rs:76:13
    |
@@ -215,28 +237,6 @@ LL |                       B(b),
 LL |               V3(c),
    |               ^^^^^ pattern doesn't bind `b`
 
-error[E0408]: variable `c` is not bound in all patterns
-  --> $DIR/missing-bindings.rs:57:13
-   |
-LL | /             V1(
-LL | |
-LL | |
-LL | |                 A(
-...  |
-LL | |                 B(Ok(a) | Err(a))
-LL | |             ) |
-   | |_____________^ pattern doesn't bind `c`
-LL | /             V2(
-LL | |                 A(
-LL | |                     A(_, a) |
-LL | |                     B(b),
-...  |
-LL | |
-LL | |             ) |
-   | |_____________^ pattern doesn't bind `c`
-LL |               V3(c),
-   |                  - variable not in all patterns
-
 error: aborting due to 26 previous errors
 
 For more information about this error, try `rustc --explain E0408`.
diff --git a/tests/ui/parser/trait-object-delimiters.rs b/tests/ui/parser/trait-object-delimiters.rs
index c41cda18743..e9b13defe03 100644
--- a/tests/ui/parser/trait-object-delimiters.rs
+++ b/tests/ui/parser/trait-object-delimiters.rs
@@ -3,9 +3,9 @@
 fn foo1(_: &dyn Drop + AsRef<str>) {} //~ ERROR ambiguous `+` in a type
 //~^ ERROR only auto traits can be used as additional traits in a trait object
 
-fn foo2(_: &dyn (Drop + AsRef<str>)) {} //~ ERROR incorrect braces around trait bounds
+fn foo2(_: &dyn (Drop + AsRef<str>)) {} //~ ERROR incorrect parentheses around trait bounds
 
-fn foo2_no_space(_: &dyn(Drop + AsRef<str>)) {} //~ ERROR incorrect braces around trait bounds
+fn foo2_no_space(_: &dyn(Drop + AsRef<str>)) {} //~ ERROR incorrect parentheses around trait bounds
 
 fn foo3(_: &dyn {Drop + AsRef<str>}) {} //~ ERROR expected parameter name, found `{`
 //~^ ERROR expected one of `!`, `(`, `)`, `*`, `,`, `?`, `for`, `~`, lifetime, or path, found `{`
diff --git a/tests/ui/parser/trait-object-delimiters.stderr b/tests/ui/parser/trait-object-delimiters.stderr
index ccce3a8053e..51954675093 100644
--- a/tests/ui/parser/trait-object-delimiters.stderr
+++ b/tests/ui/parser/trait-object-delimiters.stderr
@@ -4,28 +4,28 @@ error: ambiguous `+` in a type
 LL | fn foo1(_: &dyn Drop + AsRef<str>) {}
    |             ^^^^^^^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(dyn Drop + AsRef<str>)`
 
-error: incorrect braces around trait bounds
+error: incorrect parentheses around trait bounds
   --> $DIR/trait-object-delimiters.rs:6:17
    |
 LL | fn foo2(_: &dyn (Drop + AsRef<str>)) {}
    |                 ^                 ^
    |
-help: remove the parentheses
+help: fix the parentheses
    |
 LL - fn foo2(_: &dyn (Drop + AsRef<str>)) {}
-LL + fn foo2(_: &dyn  Drop + AsRef<str>) {}
+LL + fn foo2(_: &(dyn Drop + AsRef<str>)) {}
    |
 
-error: incorrect braces around trait bounds
+error: incorrect parentheses around trait bounds
   --> $DIR/trait-object-delimiters.rs:8:25
    |
 LL | fn foo2_no_space(_: &dyn(Drop + AsRef<str>)) {}
    |                         ^                 ^
    |
-help: remove the parentheses
+help: fix the parentheses
    |
 LL - fn foo2_no_space(_: &dyn(Drop + AsRef<str>)) {}
-LL + fn foo2_no_space(_: &dyn Drop + AsRef<str>) {}
+LL + fn foo2_no_space(_: &(dyn Drop + AsRef<str>)) {}
    |
 
 error: expected parameter name, found `{`
diff --git a/tests/ui/resolve/resolve-inconsistent-names.stderr b/tests/ui/resolve/resolve-inconsistent-names.stderr
index 023db303dd0..42b7281d7b0 100644
--- a/tests/ui/resolve/resolve-inconsistent-names.stderr
+++ b/tests/ui/resolve/resolve-inconsistent-names.stderr
@@ -14,6 +14,15 @@ LL |        a | b => {}
    |        |
    |        pattern doesn't bind `b`
 
+error[E0408]: variable `c` is not bound in all patterns
+  --> $DIR/resolve-inconsistent-names.rs:19:9
+   |
+LL |         (A, B) | (ref B, c) | (c, A) => ()
+   |         ^^^^^^           -     - variable not in all patterns
+   |         |                |
+   |         |                variable not in all patterns
+   |         pattern doesn't bind `c`
+
 error[E0408]: variable `A` is not bound in all patterns
   --> $DIR/resolve-inconsistent-names.rs:19:18
    |
@@ -37,15 +46,6 @@ LL |         (A, B) | (ref B, c) | (c, A) => ()
    |             |         variable not in all patterns
    |             variable not in all patterns
 
-error[E0408]: variable `c` is not bound in all patterns
-  --> $DIR/resolve-inconsistent-names.rs:19:9
-   |
-LL |         (A, B) | (ref B, c) | (c, A) => ()
-   |         ^^^^^^           -     - variable not in all patterns
-   |         |                |
-   |         |                variable not in all patterns
-   |         pattern doesn't bind `c`
-
 error[E0409]: variable `B` is bound inconsistently across alternatives separated by `|`
   --> $DIR/resolve-inconsistent-names.rs:19:23
    |
diff --git a/tests/ui/span/issue-39698.stderr b/tests/ui/span/issue-39698.stderr
index 25c35fd5479..81211b20a01 100644
--- a/tests/ui/span/issue-39698.stderr
+++ b/tests/ui/span/issue-39698.stderr
@@ -1,3 +1,13 @@
+error[E0408]: variable `c` is not bound in all patterns
+  --> $DIR/issue-39698.rs:10:9
+   |
+LL |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
+   |         ^^^^^^^^^^^   ^^^^^^^^^^^         -    ^^^^^^^^ pattern doesn't bind `c`
+   |         |             |                   |
+   |         |             |                   variable not in all patterns
+   |         |             pattern doesn't bind `c`
+   |         pattern doesn't bind `c`
+
 error[E0408]: variable `d` is not bound in all patterns
   --> $DIR/issue-39698.rs:10:37
    |
@@ -28,16 +38,6 @@ LL |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}
    |         |                      variable not in all patterns
    |         pattern doesn't bind `b`
 
-error[E0408]: variable `c` is not bound in all patterns
-  --> $DIR/issue-39698.rs:10:9
-   |
-LL |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
-   |         ^^^^^^^^^^^   ^^^^^^^^^^^         -    ^^^^^^^^ pattern doesn't bind `c`
-   |         |             |                   |
-   |         |             |                   variable not in all patterns
-   |         |             pattern doesn't bind `c`
-   |         pattern doesn't bind `c`
-
 error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0408`.
diff --git a/tests/ui/suggestions/copied-and-cloned.fixed b/tests/ui/suggestions/copied-and-cloned.fixed
index 77159d5075a..4cecf9e26f9 100644
--- a/tests/ui/suggestions/copied-and-cloned.fixed
+++ b/tests/ui/suggestions/copied-and-cloned.fixed
@@ -2,6 +2,16 @@
 
 fn expect<T>(_: T) {}
 
+struct Issue114925 {
+    x: Option<String>,
+}
+
+fn issue_114925(lol: &mut Issue114925, x: Option<&String>) {
+    lol.x = x.clone().cloned();
+    //~^ ERROR mismatched types
+    //~| HELP use `Option::cloned` to clone the value inside the `Option`
+}
+
 fn main() {
     let x = Some(&());
     expect::<Option<()>>(x.copied());
@@ -24,10 +34,10 @@ fn main() {
     let s = String::new();
     let x = Some(s.clone());
     let y = Some(&s);
-    println!("{}", x.as_ref() == y);
+    println!("{}", x == y.cloned());
     //~^ ERROR mismatched types
-    //~| HELP use `Option::as_ref` to convert `Option<String>` to `Option<&String>`
-
+    //~| HELP use `Option::cloned` to clone the value inside the `Option`
+    //FIXME(#114050) ~| HELP use `Option::as_ref` to convert `Option<String>` to `Option<&String>`
 
     let mut s = ();
     let x = Some(s);
@@ -42,4 +52,6 @@ fn main() {
     println!("{}", x == y.cloned());
     //~^ ERROR mismatched types
     //~| HELP use `Option::cloned` to clone the value inside the `Option`
+
+    issue_114925(&mut Issue114925 { x: None }, None);
 }
diff --git a/tests/ui/suggestions/copied-and-cloned.rs b/tests/ui/suggestions/copied-and-cloned.rs
index c506494ee14..a79928c50d5 100644
--- a/tests/ui/suggestions/copied-and-cloned.rs
+++ b/tests/ui/suggestions/copied-and-cloned.rs
@@ -2,6 +2,16 @@
 
 fn expect<T>(_: T) {}
 
+struct Issue114925 {
+    x: Option<String>,
+}
+
+fn issue_114925(lol: &mut Issue114925, x: Option<&String>) {
+    lol.x = x.clone();
+    //~^ ERROR mismatched types
+    //~| HELP use `Option::cloned` to clone the value inside the `Option`
+}
+
 fn main() {
     let x = Some(&());
     expect::<Option<()>>(x);
@@ -26,8 +36,8 @@ fn main() {
     let y = Some(&s);
     println!("{}", x == y);
     //~^ ERROR mismatched types
-    //~| HELP use `Option::as_ref` to convert `Option<String>` to `Option<&String>`
-
+    //~| HELP use `Option::cloned` to clone the value inside the `Option`
+    //FIXME(#114050) ~| HELP use `Option::as_ref` to convert `Option<String>` to `Option<&String>`
 
     let mut s = ();
     let x = Some(s);
@@ -42,4 +52,6 @@ fn main() {
     println!("{}", x == y);
     //~^ ERROR mismatched types
     //~| HELP use `Option::cloned` to clone the value inside the `Option`
+
+    issue_114925(&mut Issue114925 { x: None }, None);
 }
diff --git a/tests/ui/suggestions/copied-and-cloned.stderr b/tests/ui/suggestions/copied-and-cloned.stderr
index f8712d0a39e..87b0624d48b 100644
--- a/tests/ui/suggestions/copied-and-cloned.stderr
+++ b/tests/ui/suggestions/copied-and-cloned.stderr
@@ -1,5 +1,20 @@
 error[E0308]: mismatched types
-  --> $DIR/copied-and-cloned.rs:7:26
+  --> $DIR/copied-and-cloned.rs:10:13
+   |
+LL |     lol.x = x.clone();
+   |     -----   ^^^^^^^^^ expected `Option<String>`, found `Option<&String>`
+   |     |
+   |     expected due to the type of this binding
+   |
+   = note: expected enum `Option<String>`
+              found enum `Option<&String>`
+help: use `Option::cloned` to clone the value inside the `Option`
+   |
+LL |     lol.x = x.clone().cloned();
+   |                      +++++++++
+
+error[E0308]: mismatched types
+  --> $DIR/copied-and-cloned.rs:17:26
    |
 LL |     expect::<Option<()>>(x);
    |     -------------------- ^ expected `Option<()>`, found `Option<&()>`
@@ -19,7 +34,7 @@ LL |     expect::<Option<()>>(x.copied());
    |                           +++++++++
 
 error[E0308]: mismatched types
-  --> $DIR/copied-and-cloned.rs:11:30
+  --> $DIR/copied-and-cloned.rs:21:30
    |
 LL |     expect::<Result<(), ()>>(x);
    |     ------------------------ ^ expected `Result<(), ()>`, found `Result<&(), _>`
@@ -39,7 +54,7 @@ LL |     expect::<Result<(), ()>>(x.copied());
    |                               +++++++++
 
 error[E0308]: mismatched types
-  --> $DIR/copied-and-cloned.rs:16:30
+  --> $DIR/copied-and-cloned.rs:26:30
    |
 LL |     expect::<Option<String>>(x);
    |     ------------------------ ^ expected `Option<String>`, found `Option<&String>`
@@ -59,7 +74,7 @@ LL |     expect::<Option<String>>(x.cloned());
    |                               +++++++++
 
 error[E0308]: mismatched types
-  --> $DIR/copied-and-cloned.rs:20:34
+  --> $DIR/copied-and-cloned.rs:30:34
    |
 LL |     expect::<Result<String, ()>>(x);
    |     ---------------------------- ^ expected `Result<String, ()>`, found `Result<&String, _>`
@@ -79,20 +94,20 @@ LL |     expect::<Result<String, ()>>(x.cloned());
    |                                   +++++++++
 
 error[E0308]: mismatched types
-  --> $DIR/copied-and-cloned.rs:27:25
+  --> $DIR/copied-and-cloned.rs:37:25
    |
 LL |     println!("{}", x == y);
    |                         ^ expected `Option<String>`, found `Option<&String>`
    |
    = note: expected enum `Option<String>`
               found enum `Option<&String>`
-help: use `Option::as_ref` to convert `Option<String>` to `Option<&String>`
+help: use `Option::cloned` to clone the value inside the `Option`
    |
-LL |     println!("{}", x.as_ref() == y);
-   |                     +++++++++
+LL |     println!("{}", x == y.cloned());
+   |                          +++++++++
 
 error[E0308]: mismatched types
-  --> $DIR/copied-and-cloned.rs:35:25
+  --> $DIR/copied-and-cloned.rs:45:25
    |
 LL |     println!("{}", x == y);
    |                         ^ expected `Option<()>`, found `Option<&mut ()>`
@@ -105,7 +120,7 @@ LL |     println!("{}", x == y.copied());
    |                          +++++++++
 
 error[E0308]: mismatched types
-  --> $DIR/copied-and-cloned.rs:42:25
+  --> $DIR/copied-and-cloned.rs:52:25
    |
 LL |     println!("{}", x == y);
    |                         ^ expected `Option<String>`, found `Option<&mut String>`
@@ -117,6 +132,6 @@ help: use `Option::cloned` to clone the value inside the `Option`
 LL |     println!("{}", x == y.cloned());
    |                          +++++++++
 
-error: aborting due to 7 previous errors
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/issue-114701.rs b/tests/ui/suggestions/issue-114701.rs
new file mode 100644
index 00000000000..81d7803ec8c
--- /dev/null
+++ b/tests/ui/suggestions/issue-114701.rs
@@ -0,0 +1,15 @@
+enum Enum<T> { SVariant { v: T }, UVariant }
+
+macro_rules! is_variant {
+    (TSVariant, ) => (!);
+    (SVariant, ) => (!);
+    (UVariant, $expr:expr) => (is_variant!(@check UVariant, {}, $expr));
+    (@check $variant:ident, $matcher:tt, $expr:expr) => (
+        assert!(if let Enum::$variant::<()> $matcher = $expr () { true } else { false },
+                );
+    );
+}
+
+fn main() {
+    is_variant!(UVariant, Enum::<()>::UVariant); //~ ERROR expected function
+}
diff --git a/tests/ui/suggestions/issue-114701.stderr b/tests/ui/suggestions/issue-114701.stderr
new file mode 100644
index 00000000000..67462a09c78
--- /dev/null
+++ b/tests/ui/suggestions/issue-114701.stderr
@@ -0,0 +1,15 @@
+error[E0618]: expected function, found `Enum<()>`
+  --> $DIR/issue-114701.rs:14:27
+   |
+LL | enum Enum<T> { SVariant { v: T }, UVariant }
+   |                                   -------- `Enum::UVariant` defined here
+...
+LL |         assert!(if let Enum::$variant::<()> $matcher = $expr () { true } else { false },
+   |                                                        -------- call expression requires function
+...
+LL |     is_variant!(UVariant, Enum::<()>::UVariant);
+   |                           ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0618`.
diff --git a/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed
new file mode 100644
index 00000000000..57387936a4c
--- /dev/null
+++ b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed
@@ -0,0 +1,17 @@
+//run-rustfix
+#![allow(dead_code)]
+
+trait Trait {}
+
+fn assert_send(ptr: *mut dyn Trait) -> *mut (dyn Trait + Send) {
+    //~^ ERROR incorrect parentheses around trait bounds
+    ptr as _
+}
+
+fn foo2(_: &(dyn Trait + Send)) {}
+//~^ ERROR incorrect parentheses around trait bounds
+
+fn foo3(_: &(dyn Trait + Send)) {}
+//~^ ERROR incorrect parentheses around trait bounds
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs
new file mode 100644
index 00000000000..8a1939bcfe9
--- /dev/null
+++ b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs
@@ -0,0 +1,17 @@
+//run-rustfix
+#![allow(dead_code)]
+
+trait Trait {}
+
+fn assert_send(ptr: *mut dyn Trait) -> *mut dyn (Trait + Send) {
+    //~^ ERROR incorrect parentheses around trait bounds
+    ptr as _
+}
+
+fn foo2(_: &dyn (Trait + Send)) {}
+//~^ ERROR incorrect parentheses around trait bounds
+
+fn foo3(_: &dyn(Trait + Send)) {}
+//~^ ERROR incorrect parentheses around trait bounds
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.stderr b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.stderr
new file mode 100644
index 00000000000..2d1abe91a1e
--- /dev/null
+++ b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.stderr
@@ -0,0 +1,38 @@
+error: incorrect parentheses around trait bounds
+  --> $DIR/issue-114797-bad-parentheses-dyn-trait.rs:6:49
+   |
+LL | fn assert_send(ptr: *mut dyn Trait) -> *mut dyn (Trait + Send) {
+   |                                                 ^            ^
+   |
+help: fix the parentheses
+   |
+LL - fn assert_send(ptr: *mut dyn Trait) -> *mut dyn (Trait + Send) {
+LL + fn assert_send(ptr: *mut dyn Trait) -> *mut (dyn Trait + Send) {
+   |
+
+error: incorrect parentheses around trait bounds
+  --> $DIR/issue-114797-bad-parentheses-dyn-trait.rs:11:17
+   |
+LL | fn foo2(_: &dyn (Trait + Send)) {}
+   |                 ^            ^
+   |
+help: fix the parentheses
+   |
+LL - fn foo2(_: &dyn (Trait + Send)) {}
+LL + fn foo2(_: &(dyn Trait + Send)) {}
+   |
+
+error: incorrect parentheses around trait bounds
+  --> $DIR/issue-114797-bad-parentheses-dyn-trait.rs:14:16
+   |
+LL | fn foo3(_: &dyn(Trait + Send)) {}
+   |                ^            ^
+   |
+help: fix the parentheses
+   |
+LL - fn foo3(_: &dyn(Trait + Send)) {}
+LL + fn foo3(_: &(dyn Trait + Send)) {}
+   |
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-1.rs b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-1.rs
new file mode 100644
index 00000000000..b0b9b6bbd20
--- /dev/null
+++ b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-1.rs
@@ -0,0 +1,73 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+// A minimization of an ambiguity when using typenum. See
+// https://github.com/rust-lang/trait-system-refactor-initiative/issues/55
+// for more details.
+trait Id {
+    type Assoc: ?Sized;
+}
+impl<T: ?Sized> Id for T {
+    type Assoc = T;
+}
+
+trait WithAssoc<T: ?Sized> {
+    type Assoc: ?Sized;
+}
+
+
+struct Leaf;
+struct Wrapper<U: ?Sized>(U);
+
+impl<U: ?Sized> WithAssoc<U> for Leaf {
+    type Assoc = U;
+}
+
+impl<Ul: ?Sized, Ur: ?Sized> WithAssoc<Wrapper<Ur>> for Wrapper<Ul>
+where
+    Ul: WithAssoc<Ur>,
+{
+    type Assoc = <<Ul as WithAssoc<Ur>>::Assoc as Id>::Assoc;
+}
+
+fn bound<T: ?Sized, U: ?Sized, V: ?Sized>()
+where
+    T: WithAssoc<U, Assoc = V>,
+{
+}
+
+// normalize self type to `Wrapper<Leaf>`
+//   This succeeds, HOWEVER, instantiating the query response previously
+//   incremented the universe index counter.
+// equate impl headers:
+//      <Wrapper<Leaf> as WithAssoc<<Wrapper<Leaf> as Id>::Assoc>>
+//      <Wrapper<?2t> as WithAssoc<Wrapper<?3t>>>
+// ~> AliasRelate(<Wrapper<Leaf> as Id>::Assoc, Equate, Wrapper<?3t>)
+// add where bounds:
+// ~> Leaf: WithAssoc<?3t>
+// equate with assoc type:
+//      ?0t
+//      <Leaf as WithAssoc<?3t>>::Assoc as Id>::Assoc
+// ~> AliasRelate(
+//      <<Leaf as WithAssoc<?3t>>::Assoc as Id>::Assoc,
+//      Equate,
+//      <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc,
+//    )
+//
+// We do not reuse `?3t` during generalization because `?0t` cannot name `?4t` as we created
+// it after incrementing the universe index while normalizing the self type.
+//
+// evaluate_added_goals_and_make_query_response:
+//    AliasRelate(<Wrapper<Leaf> as Id>::Assoc, Equate, Wrapper<?3t>)
+//      YES, constrains ?3t to Leaf
+//    AliasRelate(
+//      <<Leaf as WithAssoc<Leaf>>::Assoc as Id>::Assoc,
+//      Equate,
+//      <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc,
+//    )
+//
+// Normalizing <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc then *correctly*
+// results in ambiguity.
+fn main() {
+    bound::<<Wrapper<Leaf> as Id>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
+}
diff --git a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs
new file mode 100644
index 00000000000..94d645a9859
--- /dev/null
+++ b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs
@@ -0,0 +1,75 @@
+// compile-flags: -Ztrait-solver=next
+// known-bug: trait-system-refactor-initiative#60
+
+// Generalizing a projection containing an inference variable
+// which cannot be named by the `root_vid` can result in ambiguity.
+//
+// Because we do not decrement the universe index when exiting a forall,
+// this can cause unexpected failures.
+//
+// See generalize-proj-new-universe-index-1.rs for more details.
+
+// For this reproduction we need:
+// - an inference variable with a lower universe
+// - enter a binder to increment the current universe
+// - create a new inference variable which is constrained by proving a goal
+// - equate a projection containing the new variable with the first variable
+// - generalization creates yet another inference variable which is then
+//   part of an alias-relate, resulting this to fail with ambiguity.
+//
+// Because we need to enter the binder in-between the creation of the first
+// and second inference variable, this is easiest via
+// `assemble_candidates_after_normalizing_self_ty` because eagerly call
+// `try_evaluate_added_goals` there before creating the inference variables
+// for the impl parameters.
+trait Id {
+    type Assoc: ?Sized;
+}
+impl<T: ?Sized> Id for T {
+    type Assoc = T;
+}
+
+// By adding an higher ranked bound to the impl we currently
+// propagate this bound to the caller, forcing us to create a new
+// universe.
+trait IdHigherRankedBound {
+    type Assoc: ?Sized;
+}
+
+impl<T: ?Sized> IdHigherRankedBound for T
+where
+    for<'a> T: 'a,
+{
+    type Assoc = T;
+}
+
+trait WithAssoc<T: ?Sized> {
+    type Assoc: ?Sized;
+}
+
+
+struct Leaf;
+struct Wrapper<U: ?Sized>(U);
+struct Rigid;
+
+impl<U: ?Sized> WithAssoc<U> for Leaf {
+    type Assoc = U;
+}
+
+
+impl<Ur: ?Sized> WithAssoc<Wrapper<Ur>> for Rigid
+where
+    Leaf: WithAssoc<Ur>,
+{
+    type Assoc = <<Leaf as WithAssoc<Ur>>::Assoc as Id>::Assoc;
+}
+
+fn bound<T: ?Sized, U: ?Sized, V: ?Sized>()
+where
+    T: WithAssoc<U, Assoc = V>,
+{
+}
+
+fn main() {
+    bound::<<Rigid as IdHigherRankedBound>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
+}
diff --git a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr
new file mode 100644
index 00000000000..9a8060133b8
--- /dev/null
+++ b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/generalize-proj-new-universe-index-2.rs:74:5
+   |
+LL |     bound::<<Rigid as IdHigherRankedBound>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `V` declared on the function `bound`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.rs b/tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.rs
new file mode 100644
index 00000000000..ba55ab07185
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+#![feature(non_lifetime_binders)]
+//~^ WARN is incomplete and may not be safe
+
+pub fn foo()
+where
+    for<V> V: Sized,
+{
+    bar();
+}
+
+pub fn bar()
+where
+    for<V> V: Sized,
+{
+}
+
+pub fn main() {}
diff --git a/tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.stderr b/tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.stderr
new file mode 100644
index 00000000000..e75d8127052
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/sized-late-bound-issue-114872.stderr
@@ -0,0 +1,11 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/sized-late-bound-issue-114872.rs:3:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr
index d48d9b89d1d..b612005fcb0 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr
@@ -2,22 +2,8 @@ error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>`
   --> $DIR/type-checking-test-1.rs:19:13
    |
 LL |     let _ = x as &dyn Bar<_>; // Ambiguous
-   |             ^^^^^^^^^^^^^^^^ invalid cast
-   |
-help: consider borrowing the value
-   |
-LL |     let _ = &x as &dyn Bar<_>; // Ambiguous
-   |             +
-
-error[E0277]: the trait bound `&dyn Foo: Bar<_>` is not satisfied
-  --> $DIR/type-checking-test-1.rs:19:13
-   |
-LL |     let _ = x as &dyn Bar<_>; // Ambiguous
-   |             ^ the trait `Bar<_>` is not implemented for `&dyn Foo`
-   |
-   = note: required for the cast from `&&dyn Foo` to `&dyn Bar<_>`
+   |             ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0277, E0605.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0605`.
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
index 7c7beec0809..afea8521e87 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
@@ -18,7 +18,6 @@ fn test_specific(x: &dyn Foo) {
 fn test_unknown_version(x: &dyn Foo) {
     let _ = x as &dyn Bar<_>; // Ambiguous
                               //~^ ERROR non-primitive cast
-                              //[current]~^^ ERROR the trait bound `&dyn Foo: Bar<_>` is not satisfied
 }
 
 fn test_infer_version(x: &dyn Foo) {
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.rs b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs
index 36b11dffdb1..b024b27750b 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-2.rs
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs
@@ -18,13 +18,11 @@ fn test_specific2(x: &dyn Foo<u32>) {
 fn test_specific3(x: &dyn Foo<i32>) {
     let _ = x as &dyn Bar<u32>; // Error
                                 //~^ ERROR non-primitive cast
-                                //~^^ ERROR the trait bound `&dyn Foo<i32>: Bar<u32>` is not satisfied
 }
 
 fn test_infer_arg(x: &dyn Foo<u32>) {
     let a = x as &dyn Bar<_>; // Ambiguous
                               //~^ ERROR non-primitive cast
-                              //~^^ ERROR the trait bound `&dyn Foo<u32>: Bar<_>` is not satisfied
     let _ = a.bar();
 }
 
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
index 856303ef4dd..3e59b9d3363 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
@@ -2,41 +2,14 @@ error[E0605]: non-primitive cast: `&dyn Foo<i32>` as `&dyn Bar<u32>`
   --> $DIR/type-checking-test-2.rs:19:13
    |
 LL |     let _ = x as &dyn Bar<u32>; // Error
-   |             ^^^^^^^^^^^^^^^^^^ invalid cast
-   |
-help: consider borrowing the value
-   |
-LL |     let _ = &x as &dyn Bar<u32>; // Error
-   |             +
-
-error[E0277]: the trait bound `&dyn Foo<i32>: Bar<u32>` is not satisfied
-  --> $DIR/type-checking-test-2.rs:19:13
-   |
-LL |     let _ = x as &dyn Bar<u32>; // Error
-   |             ^ the trait `Bar<u32>` is not implemented for `&dyn Foo<i32>`
-   |
-   = note: required for the cast from `&&dyn Foo<i32>` to `&dyn Bar<u32>`
+   |             ^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error[E0605]: non-primitive cast: `&dyn Foo<u32>` as `&dyn Bar<_>`
-  --> $DIR/type-checking-test-2.rs:25:13
+  --> $DIR/type-checking-test-2.rs:24:13
    |
 LL |     let a = x as &dyn Bar<_>; // Ambiguous
-   |             ^^^^^^^^^^^^^^^^ invalid cast
-   |
-help: consider borrowing the value
-   |
-LL |     let a = &x as &dyn Bar<_>; // Ambiguous
-   |             +
-
-error[E0277]: the trait bound `&dyn Foo<u32>: Bar<_>` is not satisfied
-  --> $DIR/type-checking-test-2.rs:25:13
-   |
-LL |     let a = x as &dyn Bar<_>; // Ambiguous
-   |             ^ the trait `Bar<_>` is not implemented for `&dyn Foo<u32>`
-   |
-   = note: required for the cast from `&&dyn Foo<u32>` to `&dyn Bar<_>`
+   |             ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0277, E0605.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0605`.
diff --git a/triagebot.toml b/triagebot.toml
index b2ea206a8a2..a06195cc334 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -386,7 +386,6 @@ cc = ["@camelid"]
 message = "Some changes occurred in HTML/CSS/JS."
 cc = [
     "@GuillaumeGomez",
-    "@Folyd",
     "@jsha",
 ]
 
@@ -490,7 +489,7 @@ cc = ["@nnethercote"]
 [assign]
 warn_non_default_branch = true
 contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
-users_on_vacation = ["jyn514", "WaffleLapkin", "clubby789", "oli-obk"]
+users_on_vacation = ["jyn514", "clubby789", "oli-obk"]
 
 [assign.adhoc_groups]
 compiler-team = [