about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock15
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs32
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs19
-rw-r--r--compiler/rustc_borrowck/src/invalidation.rs2
-rw-r--r--compiler/rustc_borrowck/src/lib.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs19
-rw-r--r--compiler/rustc_builtin_macros/src/concat.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/concat_bytes.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/env.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs6
-rw-r--r--compiler/rustc_codegen_gcc/src/type_.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/allocator.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs50
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs5
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs68
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/declare.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/type_.rs15
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/debuginfo.rs136
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/type_.rs1
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs18
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs16
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs39
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs3
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs19
-rw-r--r--compiler/rustc_driver/src/lib.rs9
-rw-r--r--compiler/rustc_error_messages/locales/en-US/expand.ftl107
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs6
-rw-r--r--compiler/rustc_errors/src/emitter.rs140
-rw-r--r--compiler/rustc_expand/src/base.rs92
-rw-r--r--compiler/rustc_expand/src/config.rs106
-rw-r--r--compiler/rustc_expand/src/errors.rs326
-rw-r--r--compiler/rustc_expand/src/expand.rs88
-rw-r--r--compiler/rustc_expand/src/lib.rs6
-rw-r--r--compiler/rustc_expand/src/module.rs80
-rw-r--r--compiler/rustc_expand/src/tests.rs1
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs2
-rw-r--r--compiler/rustc_hir/src/tests.rs38
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs23
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs18
-rw-r--r--compiler/rustc_hir_typeck/src/check.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs32
-rw-r--r--compiler/rustc_incremental/src/persist/fs.rs5
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs843
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_region.rs427
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/suggest.rs672
-rw-r--r--compiler/rustc_infer/src/infer/note.rs203
-rw-r--r--compiler/rustc_interface/src/passes.rs44
-rw-r--r--compiler/rustc_interface/src/queries.rs21
-rw-r--r--compiler/rustc_lint/src/builtin.rs35
-rw-r--r--compiler/rustc_lint/src/early.rs11
-rw-r--r--compiler/rustc_lint/src/hidden_unicode_codepoints.rs1
-rw-r--r--compiler/rustc_lint/src/lib.rs15
-rw-r--r--compiler/rustc_lint/src/passes.rs106
-rw-r--r--compiler/rustc_lint/src/unused.rs7
-rw-r--r--compiler/rustc_llvm/build.rs14
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp16
-rw-r--r--compiler/rustc_metadata/src/creader.rs68
-rw-r--r--compiler/rustc_metadata/src/fs.rs3
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs3
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs4
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs2
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs16
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs43
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs104
-rw-r--r--compiler/rustc_middle/src/ty/error.rs31
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs9
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs8
-rw-r--r--compiler/rustc_middle/src/ty/util.rs76
-rw-r--r--compiler/rustc_mir_build/src/build/expr/into.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs8
-rw-r--r--compiler/rustc_mir_dataflow/src/elaborate_drops.rs6
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/direction.rs4
-rw-r--r--compiler/rustc_mir_transform/src/add_retag.rs53
-rw-r--r--compiler/rustc_mir_transform/src/const_goto.rs3
-rw-r--r--compiler/rustc_mir_transform/src/coverage/tests.rs5
-rw-r--r--compiler/rustc_mir_transform/src/early_otherwise_branch.rs22
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs16
-rw-r--r--compiler/rustc_mir_transform/src/match_branches.rs12
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs11
-rw-r--r--compiler/rustc_mir_transform/src/simplify_branches.rs7
-rw-r--r--compiler/rustc_mir_transform/src/simplify_comparison_integral.rs7
-rw-r--r--compiler/rustc_mir_transform/src/unreachable_prop.rs8
-rw-r--r--compiler/rustc_parse_format/Cargo.toml1
-rw-r--r--compiler/rustc_parse_format/src/lib.rs10
-rw-r--r--compiler/rustc_parse_format/src/tests.rs80
-rw-r--r--compiler/rustc_query_system/src/ich/hcx.rs26
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs11
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs9
-rw-r--r--compiler/rustc_resolve/src/effective_visibilities.rs2
-rw-r--r--compiler/rustc_resolve/src/imports.rs2
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs9
-rw-r--r--compiler/rustc_resolve/src/lib.rs87
-rw-r--r--compiler/rustc_resolve/src/macros.rs2
-rw-r--r--compiler/rustc_save_analysis/src/dump_visitor.rs6
-rw-r--r--compiler/rustc_save_analysis/src/lib.rs8
-rw-r--r--compiler/rustc_session/Cargo.toml2
-rw-r--r--compiler/rustc_session/src/code_stats.rs5
-rw-r--r--compiler/rustc_session/src/cstore.rs16
-rw-r--r--compiler/rustc_session/src/errors.rs8
-rw-r--r--compiler/rustc_session/src/options.rs3
-rw-r--r--compiler/rustc_session/src/output.rs29
-rw-r--r--compiler/rustc_session/src/session.rs23
-rw-r--r--compiler/rustc_span/src/def_id.rs8
-rw-r--r--compiler/rustc_span/src/lib.rs9
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_symbol_mangling/Cargo.toml1
-rw-r--r--compiler/rustc_symbol_mangling/src/typeid.rs24
-rw-r--r--compiler/rustc_target/src/spec/aarch64_unknown_none.rs5
-rw-r--r--compiler/rustc_target/src/spec/apple_base.rs2
-rw-r--r--compiler/rustc_target/src/spec/mod.rs6
-rw-r--r--compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs7
-rw-r--r--compiler/rustc_target/src/spec/wasm32_wasi.rs4
-rw-r--r--compiler/rustc_target/src/spec/x86_64_unknown_none.rs3
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs370
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs13
-rw-r--r--compiler/rustc_trait_selection/src/traits/structural_match.rs48
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs10
-rw-r--r--compiler/rustc_trait_selection/src/traits/vtable.rs386
-rw-r--r--compiler/rustc_traits/src/codegen.rs (renamed from compiler/rustc_trait_selection/src/traits/codegen.rs)12
-rw-r--r--compiler/rustc_traits/src/lib.rs2
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs22
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs143
-rw-r--r--compiler/rustc_ty_utils/src/lib.rs2
-rw-r--r--compiler/rustc_ty_utils/src/structural_match.rs44
-rw-r--r--config.toml.example7
-rw-r--r--library/alloc/src/collections/vec_deque/into_iter.rs4
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs48
-rw-r--r--library/alloc/src/collections/vec_deque/spec_from_iter.rs33
-rw-r--r--library/alloc/src/vec/into_iter.rs29
-rw-r--r--library/alloc/tests/vec_deque.rs36
-rw-r--r--library/core/src/clone.rs9
-rw-r--r--library/core/src/convert/mod.rs8
-rw-r--r--library/core/src/hint.rs3
-rw-r--r--library/core/src/iter/traits/accum.rs8
-rw-r--r--library/core/src/num/mod.rs4
-rw-r--r--library/core/src/ops/mod.rs8
-rw-r--r--library/core/src/ptr/const_ptr.rs9
-rw-r--r--library/core/src/ptr/mod.rs8
-rw-r--r--library/core/src/ptr/mut_ptr.rs7
-rw-r--r--library/core/src/ptr/non_null.rs8
-rw-r--r--library/core/src/slice/mod.rs22
-rw-r--r--library/core/src/str/mod.rs4
-rw-r--r--library/std/src/fs/tests.rs16
-rw-r--r--library/std/src/sys/itron/condvar.rs4
-rw-r--r--library/std/src/sys/itron/mutex.rs2
-rw-r--r--library/std/src/sys/itron/thread.rs48
-rw-r--r--library/std/src/sys/sgx/mod.rs1
-rw-r--r--library/std/src/sys/sgx/thread.rs21
-rw-r--r--library/std/src/sys/sgx/thread_parker.rs107
-rw-r--r--library/std/src/sys/solid/io.rs4
-rw-r--r--library/std/src/sys/solid/os.rs3
-rw-r--r--library/std/src/sys/unix/fs.rs20
-rw-r--r--library/std/src/sys/unix/locks/pthread_condvar.rs93
-rw-r--r--library/std/src/sys/unix/thread.rs19
-rw-r--r--library/std/src/sys/unix/thread_parker/pthread.rs4
-rw-r--r--library/std/src/sys/unix/time.rs3
-rw-r--r--library/std/src/sys_common/thread_parker/mod.rs2
-rw-r--r--src/bootstrap/config.rs202
-rw-r--r--src/bootstrap/config/tests.rs24
-rw-r--r--src/bootstrap/defaults/config.user.toml4
-rw-r--r--src/bootstrap/lib.rs4
-rw-r--r--src/ci/docker/host-x86_64/dist-powerpc64le-linux/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile2
-rw-r--r--src/doc/unstable-book/src/compiler-flags/sanitizer.md30
-rw-r--r--src/librustdoc/config.rs5
-rw-r--r--src/librustdoc/html/render/mod.rs19
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css87
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css6
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css1
-rw-r--r--src/librustdoc/html/static/css/themes/light.css1
-rw-r--r--src/librustdoc/html/static/js/main.js2
-rw-r--r--src/librustdoc/html/static/js/scrape-examples.js32
-rw-r--r--src/librustdoc/html/static/scrape-examples-help.md5
-rw-r--r--src/librustdoc/lib.rs14
-rw-r--r--src/librustdoc/scrape_examples.rs10
-rw-r--r--src/test/codegen/catch-unwind.rs2
-rw-r--r--src/test/codegen/issue-105386-ub-in-debuginfo.rs22
-rw-r--r--src/test/codegen/remap_path_prefix/main.rs2
-rw-r--r--src/test/codegen/repr-transparent-aggregates-1.rs1
-rw-r--r--src/test/codegen/repr-transparent.rs1
-rw-r--r--src/test/codegen/sanitizer-kcfi-add-kcfi-flag.rs11
-rw-r--r--src/test/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs47
-rw-r--r--src/test/codegen/uninit-consts.rs2
-rw-r--r--src/test/mir-opt/76803_regression.encode.SimplifyBranchSame.diff2
-rw-r--r--src/test/mir-opt/bool_compare.opt1.InstCombine.diff2
-rw-r--r--src/test/mir-opt/bool_compare.opt2.InstCombine.diff2
-rw-r--r--src/test/mir-opt/bool_compare.opt3.InstCombine.diff2
-rw-r--r--src/test/mir-opt/bool_compare.opt4.InstCombine.diff2
-rw-r--r--src/test/mir-opt/building/issue_101867.main.built.after.mir2
-rw-r--r--src/test/mir-opt/building/issue_49232.main.built.after.mir2
-rw-r--r--src/test/mir-opt/building/match_false_edges.full_tested_match.built.after.mir4
-rw-r--r--src/test/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir4
-rw-r--r--src/test/mir-opt/building/match_false_edges.main.built.after.mir8
-rw-r--r--src/test/mir-opt/building/simple_match.match_bool.built.after.mir2
-rw-r--r--src/test/mir-opt/const_goto.issue_77355_opt.ConstGoto.diff6
-rw-r--r--src/test/mir-opt/const_goto_const_eval_fail.f.ConstGoto.diff6
-rw-r--r--src/test/mir-opt/const_goto_storage.match_nested_if.ConstGoto.diff10
-rw-r--r--src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff4
-rw-r--r--src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff6
-rw-r--r--src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff6
-rw-r--r--src/test/mir-opt/const_prop/switch_int.main.ConstProp.diff4
-rw-r--r--src/test/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff2
-rw-r--r--src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot2
-rw-r--r--src/test/mir-opt/dataflow-const-prop/enum.main.DataflowConstProp.diff2
-rw-r--r--src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff8
-rw-r--r--src/test/mir-opt/dataflow-const-prop/issue_81605.f.DataflowConstProp.diff4
-rw-r--r--src/test/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff4
-rw-r--r--src/test/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff2
-rw-r--r--src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff22
-rw-r--r--src/test/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir6
-rw-r--r--src/test/mir-opt/derefer_complex_case.main.Derefer.diff2
-rw-r--r--src/test/mir-opt/derefer_terminator_test.main.Derefer.diff4
-rw-r--r--src/test/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff2
-rw-r--r--src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff8
-rw-r--r--src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff10
-rw-r--r--src/test/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff8
-rw-r--r--src/test/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff12
-rw-r--r--src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff10
-rw-r--r--src/test/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff6
-rw-r--r--src/test/mir-opt/early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff4
-rw-r--r--src/test/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff4
-rw-r--r--src/test/mir-opt/equal_true.opt.InstCombine.diff2
-rw-r--r--src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir14
-rw-r--r--src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff4
-rw-r--r--src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir2
-rw-r--r--src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir2
-rw-r--r--src/test/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff2
-rw-r--r--src/test/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff2
-rw-r--r--src/test/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff4
-rw-r--r--src/test/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff4
-rw-r--r--src/test/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff4
-rw-r--r--src/test/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff8
-rw-r--r--src/test/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff4
-rw-r--r--src/test/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff4
-rw-r--r--src/test/mir-opt/inline/inline_diverging.g.Inline.diff2
-rw-r--r--src/test/mir-opt/inline/inline_generator.main.Inline.diff4
-rw-r--r--src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir4
-rw-r--r--src/test/mir-opt/inline/inline_shims.drop.Inline.diff2
-rw-r--r--src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff2
-rw-r--r--src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir2
-rw-r--r--src/test/mir-opt/issue_41110.main.ElaborateDrops.after.mir2
-rw-r--r--src/test/mir-opt/issue_41110.test.ElaborateDrops.after.mir2
-rw-r--r--src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir12
-rw-r--r--src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir2
-rw-r--r--src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff2
-rw-r--r--src/test/mir-opt/issue_99325.main.built.after.mir4
-rw-r--r--src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir4
-rw-r--r--src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff6
-rw-r--r--src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir2
-rw-r--r--src/test/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.diff2
-rw-r--r--src/test/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.diff2
-rw-r--r--src/test/mir-opt/lower_array_len_e2e.array_bound.PreCodegen.after.mir2
-rw-r--r--src/test/mir-opt/lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir2
-rw-r--r--src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff2
-rw-r--r--src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff28
-rw-r--r--src/test/mir-opt/match_test.main.SimplifyCfg-initial.after.mir12
-rw-r--r--src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff2
-rw-r--r--src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff6
-rw-r--r--src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff8
-rw-r--r--src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff2
-rw-r--r--src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff2
-rw-r--r--src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir2
-rw-r--r--src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir2
-rw-r--r--src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir2
-rw-r--r--src/test/mir-opt/not_equal_false.opt.InstCombine.diff2
-rw-r--r--src/test/mir-opt/remove_fake_borrows.match_guard.CleanupNonCodegenStatements.diff6
-rw-r--r--src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff2
-rw-r--r--src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir12
-rw-r--r--src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir1
-rw-r--r--src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir1
-rw-r--r--src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir11
-rw-r--r--src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir2
-rw-r--r--src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff10
-rw-r--r--src/test/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff8
-rw-r--r--src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff4
-rw-r--r--src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff2
-rw-r--r--src/test/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff2
-rw-r--r--src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff4
-rw-r--r--src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff2
-rw-r--r--src/test/mir-opt/simplify_match.main.ConstProp.diff4
-rw-r--r--src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir10
-rw-r--r--src/test/mir-opt/sroa.enums.ScalarReplacementOfAggregates.diff2
-rw-r--r--src/test/mir-opt/try_identity_e2e.new.PreCodegen.after.mir6
-rw-r--r--src/test/mir-opt/try_identity_e2e.old.PreCodegen.after.mir2
-rw-r--r--src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir4
-rw-r--r--src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff6
-rw-r--r--src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir4
-rw-r--r--src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff8
-rw-r--r--src/test/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff4
-rw-r--r--src/test/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff4
-rw-r--r--src/test/mir-opt/unreachable.main.UnreachablePropagation.diff6
-rw-r--r--src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff4
-rw-r--r--src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff6
-rw-r--r--src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir4
-rw-r--r--src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs2
-rw-r--r--src/test/run-make/coverage-reports/Makefile2
-rw-r--r--src/test/run-make/issue-71519/Makefile1
-rw-r--r--src/test/rustdoc-gui/basic.goml4
-rw-r--r--src/test/rustdoc-gui/docblock-table.goml47
-rw-r--r--src/test/rustdoc-gui/scrape-examples-button-focus.goml2
-rw-r--r--src/test/rustdoc-gui/scrape-examples-toggle.goml14
-rw-r--r--src/test/rustdoc-gui/src/test_docs/lib.rs3
-rw-r--r--src/test/rustdoc-gui/stab-badge.goml41
-rw-r--r--src/test/rustdoc-ui/const-evalutation-ice.rs (renamed from src/test/rustdoc/const-evalutation-ice.rs)3
-rw-r--r--src/test/rustdoc-ui/const-evalutation-ice.stderr9
-rw-r--r--src/test/rustdoc-ui/doc-cfg.stderr4
-rw-r--r--src/test/ui/async-await/in-trait/nested-rpit.rs17
-rw-r--r--src/test/ui/borrowck/issue-81899.stderr16
-rw-r--r--src/test/ui/borrowck/issue-88434-minimal-example.stderr16
-rw-r--r--src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr16
-rw-r--r--src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr2
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-105257.rs9
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-105257.stderr14
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr4
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr30
-rw-r--r--src/test/ui/const-generics/issues/issue-100313.stderr15
-rw-r--r--src/test/ui/const-ptr/forbidden_slices.32bit.stderr187
-rw-r--r--src/test/ui/const-ptr/forbidden_slices.64bit.stderr187
-rw-r--r--src/test/ui/const-ptr/out_of_bounds_read.stderr57
-rw-r--r--src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr30
-rw-r--r--src/test/ui/consts/const-eval/const_panic_track_caller.stderr15
-rw-r--r--src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr17
-rw-r--r--src/test/ui/consts/const-eval/unwind-abort.stderr16
-rw-r--r--src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr15
-rw-r--r--src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr15
-rw-r--r--src/test/ui/consts/const-float-bits-reject-conv.stderr88
-rw-r--r--src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr15
-rw-r--r--src/test/ui/consts/const_unsafe_unreachable_ub.stderr21
-rw-r--r--src/test/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr21
-rw-r--r--src/test/ui/consts/issue-miri-1910.stderr26
-rw-r--r--src/test/ui/consts/miri_unleashed/abi-mismatch.stderr15
-rw-r--r--src/test/ui/consts/miri_unleashed/assoc_const.stderr19
-rw-r--r--src/test/ui/consts/miri_unleashed/drop.stderr15
-rw-r--r--src/test/ui/consts/missing_span_in_backtrace.rs27
-rw-r--r--src/test/ui/consts/missing_span_in_backtrace.stderr28
-rw-r--r--src/test/ui/consts/offset_from_ub.stderr45
-rw-r--r--src/test/ui/consts/offset_ub.stderr180
-rw-r--r--src/test/ui/consts/ptr_comparisons.stderr15
-rw-r--r--src/test/ui/consts/recursive.stderr21
-rw-r--r--src/test/ui/consts/uninhabited-const-issue-61744.stderr775
-rw-r--r--src/test/ui/debuginfo/issue-105386-debuginfo-ub.rs20
-rw-r--r--src/test/ui/diagnostic-width/long-E0308.rs86
-rw-r--r--src/test/ui/diagnostic-width/long-E0308.stderr80
-rw-r--r--src/test/ui/error-codes/E0275.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr6
-rw-r--r--src/test/ui/inference/deref-suggestion.stderr5
-rw-r--r--src/test/ui/infinite/infinite-recursion-const-fn.stderr775
-rw-r--r--src/test/ui/invalid/invalid-no-sanitize.stderr2
-rw-r--r--src/test/ui/issues/issue-20413.stderr10
-rw-r--r--src/test/ui/issues/issue-23122-2.stderr2
-rw-r--r--src/test/ui/issues/issue-47486.stderr4
-rw-r--r--src/test/ui/limits/issue-55878.stderr12
-rw-r--r--src/test/ui/lint/lint-missing-copy-implementations-allow.rs35
-rw-r--r--src/test/ui/lint/unused/issue-54538-unused-parens-lint.fixed9
-rw-r--r--src/test/ui/lint/unused/issue-54538-unused-parens-lint.rs9
-rw-r--r--src/test/ui/lint/unused/issue-54538-unused-parens-lint.stderr36
-rw-r--r--src/test/ui/macros/macro-in-expression-context.stderr8
-rw-r--r--src/test/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs (renamed from src/test/ui/mir/issue-95978-validator-lifetime-comparison.rs)0
-rw-r--r--src/test/ui/mir/validate/needs-reveal-all.rs52
-rw-r--r--src/test/ui/numeric/numeric-cast-binop.stderr528
-rw-r--r--src/test/ui/numeric/numeric-cast-no-fix.stderr144
-rw-r--r--src/test/ui/on-unimplemented/sum.rs9
-rw-r--r--src/test/ui/on-unimplemented/sum.stderr39
-rw-r--r--src/test/ui/parser/bare-struct-body.stderr4
-rw-r--r--src/test/ui/parser/chained-comparison-suggestion.stderr24
-rw-r--r--src/test/ui/pptypedef.stderr8
-rw-r--r--src/test/ui/print_type_sizes/async.rs19
-rw-r--r--src/test/ui/print_type_sizes/async.stdout34
-rw-r--r--src/test/ui/print_type_sizes/generator.rs20
-rw-r--r--src/test/ui/print_type_sizes/generator.stdout10
-rw-r--r--src/test/ui/proc-macro/attr-invalid-exprs.stderr16
-rw-r--r--src/test/ui/proc-macro/attribute.rs8
-rw-r--r--src/test/ui/proc-macro/attribute.stderr8
-rw-r--r--src/test/ui/proc-macro/expand-expr.stderr16
-rw-r--r--src/test/ui/recursion/issue-83150.stderr2
-rw-r--r--src/test/ui/regions/issue-102374.rs1
-rw-r--r--src/test/ui/regions/issue-102374.stderr5
-rw-r--r--src/test/ui/span/issue-71363.rs2
-rw-r--r--src/test/ui/span/issue-71363.stderr2
-rw-r--r--src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr5
-rw-r--r--src/test/ui/suggestions/option-to-bool.stderr4
-rw-r--r--src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs8
-rw-r--r--src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr16
-rw-r--r--src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs14
-rw-r--r--src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr18
-rw-r--r--src/test/ui/traits/issue-91949-hangs-on-recursion.stderr2
-rw-r--r--src/test/ui/type/type-check/assignment-in-if.stderr8
-rw-r--r--src/test/ui/type/type-params-in-different-spaces-1.stderr4
-rw-r--r--src/test/ui/wrong-mul-method-signature.stderr4
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs6
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs1
-rw-r--r--src/tools/compiletest/src/header.rs2
-rw-r--r--src/tools/compiletest/src/runtest.rs2
-rw-r--r--src/tools/compiletest/src/util.rs2
-rw-r--r--src/tools/miri/src/borrow_tracker/mod.rs13
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs4
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs369
-rw-r--r--src/tools/miri/src/diagnostics.rs14
-rw-r--r--src/tools/miri/src/machine.rs22
-rw-r--r--src/tools/miri/tests/fail/abort-terminator.stderr2
-rw-r--r--src/tools/miri/tests/fail/alloc/deallocate-bad-alignment.stderr2
-rw-r--r--src/tools/miri/tests/fail/alloc/deallocate-bad-size.stderr2
-rw-r--r--src/tools/miri/tests/fail/alloc/deallocate-twice.stderr2
-rw-r--r--src/tools/miri/tests/fail/alloc/global_system_mixup.stderr2
-rw-r--r--src/tools/miri/tests/fail/alloc/reallocate-bad-size.stderr2
-rw-r--r--src/tools/miri/tests/fail/alloc/reallocate-dangling.stderr2
-rw-r--r--src/tools/miri/tests/fail/alloc/stack_free.stderr2
-rw-r--r--src/tools/miri/tests/fail/box-cell-alias.stderr2
-rw-r--r--src/tools/miri/tests/fail/concurrency/windows_join_detached.stderr2
-rw-r--r--src/tools/miri/tests/fail/crates/tokio_mvp.stderr2
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr2
-rw-r--r--src/tools/miri/tests/fail/data_race/stack_pop_race.stderr2
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr2
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr2
-rw-r--r--src/tools/miri/tests/fail/generator-pinned-moved.stderr4
-rw-r--r--src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/simd-gather.stderr2
-rw-r--r--src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr2
-rw-r--r--src/tools/miri/tests/fail/issue-miri-1112.stderr2
-rw-r--r--src/tools/miri/tests/fail/never_transmute_void.stderr2
-rw-r--r--src/tools/miri/tests/fail/panic/bad_unwind.stderr2
-rw-r--r--src/tools/miri/tests/fail/panic/double_panic.stderr4
-rw-r--r--src/tools/miri/tests/fail/panic/no_std.stderr2
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort1.stderr2
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort2.stderr2
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort3.stderr2
-rw-r--r--src/tools/miri/tests/fail/panic/panic_abort4.stderr2
-rw-r--r--src/tools/miri/tests/fail/provenance/provenance_transmute.stderr2
-rw-r--r--src/tools/miri/tests/fail/shims/fs/isolated_file.stderr2
-rw-r--r--src/tools/miri/tests/fail/shims/fs/mkstemp_immutable_arg.stderr2
-rw-r--r--src/tools/miri/tests/fail/shims/fs/unix_open_missing_required_mode.stderr2
-rw-r--r--src/tools/miri/tests/fail/should-pass/cpp20_rwc_syncs.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/aliasing_mut1.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/aliasing_mut2.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/aliasing_mut3.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/aliasing_mut4.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/box_exclusive_violation1.stderr4
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/box_noalias_violation.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.stderr6
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector2.stderr6
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/illegal_write6.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector2.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector3.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-1.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-2.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation1.stderr4
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.stderr6
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.stderr6
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr2
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/shr_frozen_violation1.stderr4
-rw-r--r--src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr2
-rw-r--r--src/tools/miri/tests/fail/uninit_buffer.stderr2
-rw-r--r--src/tools/miri/tests/fail/uninit_buffer_with_provenance.stderr2
-rw-r--r--src/tools/miri/tests/pass/box.stderr4
-rw-r--r--src/tools/tidy/src/deps.rs2
-rw-r--r--src/version2
484 files changed, 8383 insertions, 4197 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 150a70341f5..37bbe95d633 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4168,6 +4168,7 @@ dependencies = [
 name = "rustc_parse_format"
 version = "0.0.0"
 dependencies = [
+ "rustc_data_structures",
  "rustc_lexer",
 ]
 
@@ -4342,12 +4343,14 @@ dependencies = [
  "rustc_feature",
  "rustc_fs_util",
  "rustc_hir",
+ "rustc_index",
  "rustc_lint_defs",
  "rustc_macros",
  "rustc_serialize",
  "rustc_span",
  "rustc_target",
  "smallvec",
+ "termize",
  "tracing",
  "winapi",
 ]
@@ -4401,6 +4404,7 @@ dependencies = [
  "rustc_span",
  "rustc_target",
  "tracing",
+ "twox-hash",
 ]
 
 [[package]]
@@ -5392,6 +5396,17 @@ dependencies = [
 ]
 
 [[package]]
+name = "twox-hash"
+version = "1.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
+dependencies = [
+ "cfg-if 1.0.0",
+ "rand 0.8.5",
+ "static_assertions",
+]
+
+[[package]]
 name = "type-map"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 07558ca075d..4fa18907fcd 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -259,6 +259,8 @@ enum ImplTraitContext {
     },
     /// Impl trait in type aliases.
     TypeAliasesOpaqueTy,
+    /// `impl Trait` is unstably accepted in this position.
+    FeatureGated(ImplTraitPosition, Symbol),
     /// `impl Trait` is not accepted in this position.
     Disallowed(ImplTraitPosition),
 }
@@ -1372,17 +1374,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         }
                         path
                     }
-                    ImplTraitContext::Disallowed(
-                        position @ (ImplTraitPosition::TraitReturn | ImplTraitPosition::ImplReturn),
-                    ) => {
+                    ImplTraitContext::FeatureGated(position, feature) => {
                         self.tcx
                             .sess
                             .create_feature_err(
                                 MisplacedImplTrait {
                                     span: t.span,
-                                    position: DiagnosticArgFromDisplay(&position),
+                                    position: DiagnosticArgFromDisplay(position),
                                 },
-                                sym::return_position_impl_trait_in_trait,
+                                *feature,
                             )
                             .emit();
                         hir::TyKind::Err
@@ -1390,7 +1390,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     ImplTraitContext::Disallowed(position) => {
                         self.tcx.sess.emit_err(MisplacedImplTrait {
                             span: t.span,
-                            position: DiagnosticArgFromDisplay(&position),
+                            position: DiagnosticArgFromDisplay(position),
                         });
                         hir::TyKind::Err
                     }
@@ -1739,14 +1739,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         } else {
             match &decl.output {
                 FnRetTy::Ty(ty) => {
-                    let mut context = if kind.return_impl_trait_allowed(self.tcx) {
+                    let context = if kind.return_impl_trait_allowed(self.tcx) {
                         let fn_def_id = self.local_def_id(fn_node_id);
                         ImplTraitContext::ReturnPositionOpaqueTy {
                             origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
                             in_trait: matches!(kind, FnDeclKind::Trait),
                         }
                     } else {
-                        ImplTraitContext::Disallowed(match kind {
+                        let position = match kind {
                             FnDeclKind::Fn | FnDeclKind::Inherent => {
                                 unreachable!("fn should allow in-band lifetimes")
                             }
@@ -1755,9 +1755,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             FnDeclKind::Pointer => ImplTraitPosition::PointerReturn,
                             FnDeclKind::Trait => ImplTraitPosition::TraitReturn,
                             FnDeclKind::Impl => ImplTraitPosition::ImplReturn,
-                        })
+                        };
+                        match kind {
+                            FnDeclKind::Trait | FnDeclKind::Impl => ImplTraitContext::FeatureGated(
+                                position,
+                                sym::return_position_impl_trait_in_trait,
+                            ),
+                            _ => ImplTraitContext::Disallowed(position),
+                        }
                     };
-                    hir::FnRetTy::Return(self.lower_ty(ty, &mut context))
+                    hir::FnRetTy::Return(self.lower_ty(ty, &context))
                 }
                 FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(self.lower_span(*span)),
             }
@@ -1938,7 +1945,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     output,
                     span,
                     if in_trait && !this.tcx.features().return_position_impl_trait_in_trait {
-                        ImplTraitContext::Disallowed(ImplTraitPosition::TraitReturn)
+                        ImplTraitContext::FeatureGated(
+                            ImplTraitPosition::TraitReturn,
+                            sym::return_position_impl_trait_in_trait,
+                        )
                     } else {
                         ImplTraitContext::ReturnPositionOpaqueTy {
                             origin: hir::OpaqueTyOrigin::FnReturn(fn_def_id),
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 8d23c26e603..592fc5aa645 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -9,7 +9,7 @@ use rustc_ast::{self as ast, *};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, PartialRes, Res};
 use rustc_hir::GenericArg;
-use rustc_span::symbol::{kw, Ident};
+use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{BytePos, Span, DUMMY_SP};
 
 use smallvec::{smallvec, SmallVec};
@@ -352,11 +352,18 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             // fn f(_: impl Fn() -> impl Debug) -> impl Fn() -> impl Debug
             // //      disallowed --^^^^^^^^^^        allowed --^^^^^^^^^^
             // ```
-            FnRetTy::Ty(ty)
-                if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. })
-                    && self.tcx.features().impl_trait_in_fn_trait_return =>
-            {
-                self.lower_ty(&ty, itctx)
+            FnRetTy::Ty(ty) if matches!(itctx, ImplTraitContext::ReturnPositionOpaqueTy { .. }) => {
+                if self.tcx.features().impl_trait_in_fn_trait_return {
+                    self.lower_ty(&ty, itctx)
+                } else {
+                    self.lower_ty(
+                        &ty,
+                        &ImplTraitContext::FeatureGated(
+                            ImplTraitPosition::FnTraitReturn,
+                            sym::impl_trait_in_fn_trait_return,
+                        ),
+                    )
+                }
             }
             FnRetTy::Ty(ty) => {
                 self.lower_ty(&ty, &ImplTraitContext::Disallowed(ImplTraitPosition::FnTraitReturn))
diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs
index f66a7ab3c03..6fd9290058c 100644
--- a/compiler/rustc_borrowck/src/invalidation.rs
+++ b/compiler/rustc_borrowck/src/invalidation.rs
@@ -106,7 +106,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
         self.check_activations(location);
 
         match &terminator.kind {
-            TerminatorKind::SwitchInt { discr, switch_ty: _, targets: _ } => {
+            TerminatorKind::SwitchInt { discr, targets: _ } => {
                 self.consume_operand(location, discr);
             }
             TerminatorKind::Drop { place: drop_place, target: _, unwind: _ } => {
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 74b4e4a0cab..5289de9b0ab 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -644,7 +644,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
         self.check_activations(loc, span, flow_state);
 
         match &term.kind {
-            TerminatorKind::SwitchInt { discr, switch_ty: _, targets: _ } => {
+            TerminatorKind::SwitchInt { discr, targets: _ } => {
                 self.consume_operand(loc, (discr, span), flow_state);
             }
             TerminatorKind::Drop { place, target: _, unwind: _ } => {
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 6d4ec6b726e..814bc275019 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1360,25 +1360,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     );
                 }
             }
-            TerminatorKind::SwitchInt { discr, switch_ty, .. } => {
+            TerminatorKind::SwitchInt { discr, .. } => {
                 self.check_operand(discr, term_location);
 
-                let discr_ty = discr.ty(body, tcx);
-                if let Err(terr) = self.sub_types(
-                    discr_ty,
-                    *switch_ty,
-                    term_location.to_locations(),
-                    ConstraintCategory::Assignment,
-                ) {
-                    span_mirbug!(
-                        self,
-                        term,
-                        "bad SwitchInt ({:?} on {:?}): {:?}",
-                        switch_ty,
-                        discr_ty,
-                        terr
-                    );
-                }
+                let switch_ty = discr.ty(body, tcx);
                 if !switch_ty.is_integral() && !switch_ty.is_char() && !switch_ty.is_bool() {
                     span_mirbug!(self, term, "bad SwitchInt discr ty {:?}", switch_ty);
                 }
diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs
index e2d71825d55..9ae65c641fd 100644
--- a/compiler/rustc_builtin_macros/src/concat.rs
+++ b/compiler/rustc_builtin_macros/src/concat.rs
@@ -11,7 +11,7 @@ pub fn expand_concat(
     sp: rustc_span::Span,
     tts: TokenStream,
 ) -> Box<dyn base::MacResult + 'static> {
-    let Some(es) = base::get_exprs_from_tts(cx, sp, tts) else {
+    let Some(es) = base::get_exprs_from_tts(cx, tts) else {
         return DummyResult::any(sp);
     };
     let mut accumulator = String::new();
diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs
index d1124145dcb..70ce5a6c419 100644
--- a/compiler/rustc_builtin_macros/src/concat_bytes.rs
+++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs
@@ -137,7 +137,7 @@ pub fn expand_concat_bytes(
     sp: rustc_span::Span,
     tts: TokenStream,
 ) -> Box<dyn base::MacResult + 'static> {
-    let Some(es) = base::get_exprs_from_tts(cx, sp, tts) else {
+    let Some(es) = base::get_exprs_from_tts(cx, tts) else {
         return DummyResult::any(sp);
     };
     let mut accumulator = Vec::new();
diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs
index 0b4e545f7a3..a7283ea601b 100644
--- a/compiler/rustc_builtin_macros/src/env.rs
+++ b/compiler/rustc_builtin_macros/src/env.rs
@@ -52,7 +52,7 @@ pub fn expand_env<'cx>(
     sp: Span,
     tts: TokenStream,
 ) -> Box<dyn base::MacResult + 'cx> {
-    let mut exprs = match get_exprs_from_tts(cx, sp, tts) {
+    let mut exprs = match get_exprs_from_tts(cx, tts) {
         Some(exprs) if exprs.is_empty() => {
             cx.span_err(sp, "env! takes 1 or 2 arguments");
             return DummyResult::any(sp);
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 8b07c110663..63bc0d552c1 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -333,7 +333,7 @@ pub fn make_format_args(
             parse::Piece::String(s) => {
                 unfinished_literal.push_str(s);
             }
-            parse::Piece::NextArgument(parse::Argument { position, position_span, format }) => {
+            parse::Piece::NextArgument(box parse::Argument { position, position_span, format }) => {
                 if !unfinished_literal.is_empty() {
                     template.push(FormatArgsPiece::Literal(Symbol::intern(&unfinished_literal)));
                     unfinished_literal.clear();
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 1db44502742..06813d7ec95 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -372,8 +372,10 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
                 }
             }
 
-            TerminatorKind::SwitchInt { discr, switch_ty, targets } => {
-                let discr = codegen_operand(fx, discr).load_scalar(fx);
+            TerminatorKind::SwitchInt { discr, targets } => {
+                let discr = codegen_operand(fx, discr);
+                let switch_ty = discr.layout().ty;
+                let discr = discr.load_scalar(fx);
 
                 let use_bool_opt = switch_ty.kind() == fx.tcx.types.bool.kind()
                     || (targets.iter().count() == 1 && targets.iter().next().unwrap().0 == 0);
diff --git a/compiler/rustc_codegen_gcc/src/type_.rs b/compiler/rustc_codegen_gcc/src/type_.rs
index bdf7318ce48..89a415cdb36 100644
--- a/compiler/rustc_codegen_gcc/src/type_.rs
+++ b/compiler/rustc_codegen_gcc/src/type_.rs
@@ -300,4 +300,8 @@ impl<'gcc, 'tcx> TypeMembershipMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         // Unsupported.
         self.context.new_rvalue_from_int(self.int_type, 0)
     }
+
+    fn set_kcfi_type_metadata(&self, _function: RValue<'gcc>, _kcfi_typeid: u32) {
+        // Unsupported.
+    }
 }
diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs
index fed56cdd438..668d9292705 100644
--- a/compiler/rustc_codegen_llvm/src/allocator.rs
+++ b/compiler/rustc_codegen_llvm/src/allocator.rs
@@ -88,7 +88,8 @@ pub(crate) unsafe fn codegen(
             callee,
             args.as_ptr(),
             args.len() as c_uint,
-            None,
+            [].as_ptr(),
+            0 as c_uint,
         );
         llvm::LLVMSetTailCall(ret, True);
         if output.is_some() {
@@ -132,8 +133,15 @@ pub(crate) unsafe fn codegen(
         .enumerate()
         .map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint))
         .collect::<Vec<_>>();
-    let ret =
-        llvm::LLVMRustBuildCall(llbuilder, ty, callee, args.as_ptr(), args.len() as c_uint, None);
+    let ret = llvm::LLVMRustBuildCall(
+        llbuilder,
+        ty,
+        callee,
+        args.as_ptr(),
+        args.len() as c_uint,
+        [].as_ptr(),
+        0 as c_uint,
+    );
     llvm::LLVMSetTailCall(ret, True);
     llvm::LLVMBuildRetVoid(llbuilder);
     llvm::LLVMDisposeBuilder(llbuilder);
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 77dd15ef4d8..83bffb20e0c 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -20,6 +20,7 @@ use rustc_middle::ty::layout::{
 };
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::Span;
+use rustc_symbol_mangling::typeid::kcfi_typeid_for_fnabi;
 use rustc_target::abi::{self, call::FnAbi, Align, Size, WrappingRange};
 use rustc_target::spec::{HasTargetSpec, Target};
 use std::borrow::Cow;
@@ -225,9 +226,25 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         debug!("invoke {:?} with args ({:?})", llfn, args);
 
         let args = self.check_call("invoke", llty, llfn, args);
-        let bundle = funclet.map(|funclet| funclet.bundle());
-        let bundle = bundle.as_ref().map(|b| &*b.raw);
+        let funclet_bundle = funclet.map(|funclet| funclet.bundle());
+        let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw);
+        let mut bundles = vec![funclet_bundle];
+
+        // Set KCFI operand bundle
+        let is_indirect_call = unsafe { llvm::LLVMIsAFunction(llfn).is_none() };
+        let kcfi_bundle =
+            if self.tcx.sess.is_sanitizer_kcfi_enabled() && fn_abi.is_some() && is_indirect_call {
+                let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi.unwrap());
+                Some(llvm::OperandBundleDef::new("kcfi", &[self.const_u32(kcfi_typeid)]))
+            } else {
+                None
+            };
+        if kcfi_bundle.is_some() {
+            let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
+            bundles.push(kcfi_bundle);
+        }
 
+        bundles.retain(|bundle| bundle.is_some());
         let invoke = unsafe {
             llvm::LLVMRustBuildInvoke(
                 self.llbuilder,
@@ -237,7 +254,8 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
                 args.len() as c_uint,
                 then,
                 catch,
-                bundle,
+                bundles.as_ptr(),
+                bundles.len() as c_uint,
                 UNNAMED,
             )
         };
@@ -1143,7 +1161,8 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
                 llfn,
                 args.as_ptr() as *const &llvm::Value,
                 args.len() as c_uint,
-                None,
+                [].as_ptr(),
+                0 as c_uint,
             );
         }
     }
@@ -1159,9 +1178,25 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         debug!("call {:?} with args ({:?})", llfn, args);
 
         let args = self.check_call("call", llty, llfn, args);
-        let bundle = funclet.map(|funclet| funclet.bundle());
-        let bundle = bundle.as_ref().map(|b| &*b.raw);
+        let funclet_bundle = funclet.map(|funclet| funclet.bundle());
+        let funclet_bundle = funclet_bundle.as_ref().map(|b| &*b.raw);
+        let mut bundles = vec![funclet_bundle];
+
+        // Set KCFI operand bundle
+        let is_indirect_call = unsafe { llvm::LLVMIsAFunction(llfn).is_none() };
+        let kcfi_bundle =
+            if self.tcx.sess.is_sanitizer_kcfi_enabled() && fn_abi.is_some() && is_indirect_call {
+                let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi.unwrap());
+                Some(llvm::OperandBundleDef::new("kcfi", &[self.const_u32(kcfi_typeid)]))
+            } else {
+                None
+            };
+        if kcfi_bundle.is_some() {
+            let kcfi_bundle = kcfi_bundle.as_ref().map(|b| &*b.raw);
+            bundles.push(kcfi_bundle);
+        }
 
+        bundles.retain(|bundle| bundle.is_some());
         let call = unsafe {
             llvm::LLVMRustBuildCall(
                 self.llbuilder,
@@ -1169,7 +1204,8 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
                 llfn,
                 args.as_ptr() as *const &llvm::Value,
                 args.len() as c_uint,
-                bundle,
+                bundles.as_ptr(),
+                bundles.len() as c_uint,
             )
         };
         if let Some(fn_abi) = fn_abi {
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 4dcc7cd5447..aa1735f38ac 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -250,6 +250,11 @@ pub unsafe fn create_module<'ll>(
         );
     }
 
+    if sess.is_sanitizer_kcfi_enabled() {
+        let kcfi = "kcfi\0".as_ptr().cast();
+        llvm::LLVMRustAddModuleFlag(llmod, llvm::LLVMModFlagBehavior::Override, kcfi, 1);
+    }
+
     // Control Flow Guard is currently only supported by the MSVC linker on Windows.
     if sess.target.is_like_msvc {
         match sess.opts.cg.control_flow_guard {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index d87117dffdc..a9e3dcf4cb3 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -27,9 +27,7 @@ use rustc_codegen_ssa::traits::*;
 use rustc_fs_util::path_to_c_string;
 use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
-use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::bug;
-use rustc_middle::mir::{self, GeneratorLayout};
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{
@@ -1026,33 +1024,6 @@ fn build_struct_type_di_node<'ll, 'tcx>(
 // Tuples
 //=-----------------------------------------------------------------------------
 
-/// Returns names of captured upvars for closures and generators.
-///
-/// Here are some examples:
-///  - `name__field1__field2` when the upvar is captured by value.
-///  - `_ref__name__field` when the upvar is captured by reference.
-///
-/// For generators this only contains upvars that are shared by all states.
-fn closure_saved_names_of_captured_variables(tcx: TyCtxt<'_>, def_id: DefId) -> SmallVec<String> {
-    let body = tcx.optimized_mir(def_id);
-
-    body.var_debug_info
-        .iter()
-        .filter_map(|var| {
-            let is_ref = match var.value {
-                mir::VarDebugInfoContents::Place(place) if place.local == mir::Local::new(1) => {
-                    // The projection is either `[.., Field, Deref]` or `[.., Field]`. It
-                    // implies whether the variable is captured by value or by reference.
-                    matches!(place.projection.last().unwrap(), mir::ProjectionElem::Deref)
-                }
-                _ => return None,
-            };
-            let prefix = if is_ref { "_ref__" } else { "" };
-            Some(prefix.to_owned() + var.name.as_str())
-        })
-        .collect()
-}
-
 /// Builds the DW_TAG_member debuginfo nodes for the upvars of a closure or generator.
 /// For a generator, this will handle upvars shared by all states.
 fn build_upvar_field_di_nodes<'ll, 'tcx>(
@@ -1083,7 +1054,7 @@ fn build_upvar_field_di_nodes<'ll, 'tcx>(
             .all(|&t| t == cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t))
     );
 
-    let capture_names = closure_saved_names_of_captured_variables(cx.tcx, def_id);
+    let capture_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);
     let layout = cx.layout_of(closure_or_generator_ty);
 
     up_var_tys
@@ -1229,43 +1200,6 @@ fn build_union_type_di_node<'ll, 'tcx>(
     )
 }
 
-// FIXME(eddyb) maybe precompute this? Right now it's computed once
-// per generator monomorphization, but it doesn't depend on substs.
-fn generator_layout_and_saved_local_names<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    def_id: DefId,
-) -> (&'tcx GeneratorLayout<'tcx>, IndexVec<mir::GeneratorSavedLocal, Option<Symbol>>) {
-    let body = tcx.optimized_mir(def_id);
-    let generator_layout = body.generator_layout().unwrap();
-    let mut generator_saved_local_names = IndexVec::from_elem(None, &generator_layout.field_tys);
-
-    let state_arg = mir::Local::new(1);
-    for var in &body.var_debug_info {
-        let mir::VarDebugInfoContents::Place(place) = &var.value else { continue };
-        if place.local != state_arg {
-            continue;
-        }
-        match place.projection[..] {
-            [
-                // Deref of the `Pin<&mut Self>` state argument.
-                mir::ProjectionElem::Field(..),
-                mir::ProjectionElem::Deref,
-                // Field of a variant of the state.
-                mir::ProjectionElem::Downcast(_, variant),
-                mir::ProjectionElem::Field(field, _),
-            ] => {
-                let name = &mut generator_saved_local_names
-                    [generator_layout.variant_fields[variant][field]];
-                if name.is_none() {
-                    name.replace(var.name);
-                }
-            }
-            _ => {}
-        }
-    }
-    (generator_layout, generator_saved_local_names)
-}
-
 /// Computes the type parameters for a type, if any, for the given metadata.
 fn build_generic_type_param_di_nodes<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
index 53e8a291d1e..69443b9b828 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
@@ -22,9 +22,9 @@ use crate::{
     common::CodegenCx,
     debuginfo::{
         metadata::{
-            build_field_di_node, closure_saved_names_of_captured_variables,
+            build_field_di_node,
             enums::{tag_base_type, DiscrResult},
-            file_metadata, generator_layout_and_saved_local_names, size_and_align_of, type_di_node,
+            file_metadata, size_and_align_of, type_di_node,
             type_map::{self, Stub, UniqueTypeId},
             unknown_file_metadata, DINodeCreationResult, SmallVec, NO_GENERICS, NO_SCOPE_METADATA,
             UNKNOWN_LINE_NUMBER,
@@ -677,9 +677,9 @@ fn build_union_fields_for_direct_tag_generator<'ll, 'tcx>(
     };
 
     let (generator_layout, state_specific_upvar_names) =
-        generator_layout_and_saved_local_names(cx.tcx, generator_def_id);
+        cx.tcx.generator_layout_and_saved_local_names(generator_def_id);
 
-    let common_upvar_names = closure_saved_names_of_captured_variables(cx.tcx, generator_def_id);
+    let common_upvar_names = cx.tcx.closure_saved_names_of_captured_variables(generator_def_id);
     let variant_range = generator_substs.variant_range(generator_def_id, cx.tcx);
     let variant_count = (variant_range.start.as_u32()..variant_range.end.as_u32()).len();
 
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
index becbccc434d..93419d27a62 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
@@ -4,9 +4,8 @@ use crate::{
     common::CodegenCx,
     debuginfo::{
         metadata::{
-            closure_saved_names_of_captured_variables,
             enums::tag_base_type,
-            file_metadata, generator_layout_and_saved_local_names, size_and_align_of, type_di_node,
+            file_metadata, size_and_align_of, type_di_node,
             type_map::{self, Stub, StubInfo, UniqueTypeId},
             unknown_file_metadata, DINodeCreationResult, SmallVec, NO_GENERICS,
             UNKNOWN_LINE_NUMBER,
@@ -157,7 +156,7 @@ pub(super) fn build_generator_di_node<'ll, 'tcx>(
         ),
         |cx, generator_type_di_node| {
             let (generator_layout, state_specific_upvar_names) =
-                generator_layout_and_saved_local_names(cx.tcx, generator_def_id);
+                cx.tcx.generator_layout_and_saved_local_names(generator_def_id);
 
             let Variants::Multiple { tag_encoding: TagEncoding::Direct, ref variants, .. } = generator_type_and_layout.variants else {
                 bug!(
@@ -167,7 +166,7 @@ pub(super) fn build_generator_di_node<'ll, 'tcx>(
             };
 
             let common_upvar_names =
-                closure_saved_names_of_captured_variables(cx.tcx, generator_def_id);
+                cx.tcx.closure_saved_names_of_captured_variables(generator_def_id);
 
             // Build variant struct types
             let variant_struct_type_di_nodes: SmallVec<_> = variants
diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs
index dc21a02cec4..6a575095f7e 100644
--- a/compiler/rustc_codegen_llvm/src/declare.rs
+++ b/compiler/rustc_codegen_llvm/src/declare.rs
@@ -20,7 +20,7 @@ use crate::type_::Type;
 use crate::value::Value;
 use rustc_codegen_ssa::traits::TypeMembershipMethods;
 use rustc_middle::ty::Ty;
-use rustc_symbol_mangling::typeid::typeid_for_fnabi;
+use rustc_symbol_mangling::typeid::{kcfi_typeid_for_fnabi, typeid_for_fnabi};
 use smallvec::SmallVec;
 
 /// Declare a function.
@@ -136,6 +136,11 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
             self.set_type_metadata(llfn, typeid);
         }
 
+        if self.tcx.sess.is_sanitizer_kcfi_enabled() {
+            let kcfi_typeid = kcfi_typeid_for_fnabi(self.tcx, fn_abi);
+            self.set_kcfi_type_metadata(llfn, kcfi_typeid);
+        }
+
         llfn
     }
 
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 8a9392255b8..e61dbe8b8fc 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -427,6 +427,7 @@ pub enum MetadataType {
     MD_type = 19,
     MD_vcall_visibility = 28,
     MD_noundef = 29,
+    MD_kcfi_type = 36,
 }
 
 /// LLVMRustAsmDialect
@@ -1063,6 +1064,7 @@ extern "C" {
     pub fn LLVMGlobalSetMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata);
     pub fn LLVMRustGlobalAddMetadata<'a>(Val: &'a Value, KindID: c_uint, Metadata: &'a Metadata);
     pub fn LLVMValueAsMetadata(Node: &Value) -> &Metadata;
+    pub fn LLVMIsAFunction(Val: &Value) -> Option<&Value>;
 
     // Operations on constants of any type
     pub fn LLVMConstNull(Ty: &Type) -> &Value;
@@ -1273,7 +1275,8 @@ extern "C" {
         NumArgs: c_uint,
         Then: &'a BasicBlock,
         Catch: &'a BasicBlock,
-        Bundle: Option<&OperandBundleDef<'a>>,
+        OpBundles: *const Option<&OperandBundleDef<'a>>,
+        NumOpBundles: c_uint,
         Name: *const c_char,
     ) -> &'a Value;
     pub fn LLVMBuildLandingPad<'a>(
@@ -1643,7 +1646,8 @@ extern "C" {
         Fn: &'a Value,
         Args: *const &'a Value,
         NumArgs: c_uint,
-        Bundle: Option<&OperandBundleDef<'a>>,
+        OpBundles: *const Option<&OperandBundleDef<'a>>,
+        NumOpBundles: c_uint,
     ) -> &'a Value;
     pub fn LLVMRustBuildMemCpy<'a>(
         B: &Builder<'a>,
diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs
index 5772b7e1d81..ff111d96f84 100644
--- a/compiler/rustc_codegen_llvm/src/type_.rs
+++ b/compiler/rustc_codegen_llvm/src/type_.rs
@@ -316,4 +316,19 @@ impl<'ll, 'tcx> TypeMembershipMethods<'tcx> for CodegenCx<'ll, 'tcx> {
             )
         }
     }
+
+    fn set_kcfi_type_metadata(&self, function: &'ll Value, kcfi_typeid: u32) {
+        let kcfi_type_metadata = self.const_u32(kcfi_typeid);
+        unsafe {
+            llvm::LLVMGlobalSetMetadata(
+                function,
+                llvm::MD_kcfi_type as c_uint,
+                llvm::LLVMMDNodeInContext2(
+                    self.llcx,
+                    &llvm::LLVMValueAsMetadata(kcfi_type_metadata),
+                    1,
+                ),
+            )
+        }
+    }
 }
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 540f15c89e9..882430694e1 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -102,7 +102,7 @@ pub fn link_binary<'a>(
                 sess,
                 crate_type,
                 outputs,
-                codegen_results.crate_info.local_crate_name.as_str(),
+                codegen_results.crate_info.local_crate_name,
             );
             match crate_type {
                 CrateType::Rlib => {
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 03d833fbba8..f3f5ddb52d6 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -307,12 +307,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         helper: TerminatorCodegenHelper<'tcx>,
         bx: &mut Bx,
         discr: &mir::Operand<'tcx>,
-        switch_ty: Ty<'tcx>,
         targets: &SwitchTargets,
     ) {
         let discr = self.codegen_operand(bx, &discr);
-        // `switch_ty` is redundant, sanity-check that.
-        assert_eq!(discr.layout.ty, switch_ty);
+        let switch_ty = discr.layout.ty;
         let mut target_iter = targets.iter();
         if target_iter.len() == 1 {
             // If there are two targets (one conditional, one fallback), emit `br` instead of
@@ -1293,8 +1291,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 helper.funclet_br(self, bx, target, mergeable_succ())
             }
 
-            mir::TerminatorKind::SwitchInt { ref discr, switch_ty, ref targets } => {
-                self.codegen_switchint_terminator(helper, bx, discr, switch_ty, targets);
+            mir::TerminatorKind::SwitchInt { ref discr, ref targets } => {
+                self.codegen_switchint_terminator(helper, bx, discr, targets);
                 MergingSucc::False
             }
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index 99283d3bb29..b7982b633f5 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -3,12 +3,12 @@ use rustc_index::vec::IndexVec;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir;
 use rustc_middle::ty;
+use rustc_middle::ty::layout::TyAndLayout;
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
 use rustc_session::config::DebugInfo;
 use rustc_span::symbol::{kw, Symbol};
 use rustc_span::{BytePos, Span};
-use rustc_target::abi::Abi;
-use rustc_target::abi::Size;
+use rustc_target::abi::{Abi, Size, VariantIdx};
 
 use super::operand::{OperandRef, OperandValue};
 use super::place::PlaceRef;
@@ -76,6 +76,106 @@ impl<'tcx, S: Copy, L: Copy> DebugScope<S, L> {
     }
 }
 
+trait DebugInfoOffsetLocation<'tcx, Bx> {
+    fn deref(&self, bx: &mut Bx) -> Self;
+    fn layout(&self) -> TyAndLayout<'tcx>;
+    fn project_field(&self, bx: &mut Bx, field: mir::Field) -> Self;
+    fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self;
+}
+
+impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
+    for PlaceRef<'tcx, Bx::Value>
+{
+    fn deref(&self, bx: &mut Bx) -> Self {
+        bx.load_operand(*self).deref(bx.cx())
+    }
+
+    fn layout(&self) -> TyAndLayout<'tcx> {
+        self.layout
+    }
+
+    fn project_field(&self, bx: &mut Bx, field: mir::Field) -> Self {
+        PlaceRef::project_field(*self, bx, field.index())
+    }
+
+    fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self {
+        self.project_downcast(bx, variant)
+    }
+}
+
+impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> DebugInfoOffsetLocation<'tcx, Bx>
+    for TyAndLayout<'tcx>
+{
+    fn deref(&self, bx: &mut Bx) -> Self {
+        bx.cx().layout_of(
+            self.ty.builtin_deref(true).unwrap_or_else(|| bug!("cannot deref `{}`", self.ty)).ty,
+        )
+    }
+
+    fn layout(&self) -> TyAndLayout<'tcx> {
+        *self
+    }
+
+    fn project_field(&self, bx: &mut Bx, field: mir::Field) -> Self {
+        self.field(bx.cx(), field.index())
+    }
+
+    fn downcast(&self, bx: &mut Bx, variant: VariantIdx) -> Self {
+        self.for_variant(bx.cx(), variant)
+    }
+}
+
+struct DebugInfoOffset<T> {
+    /// Offset from the `base` used to calculate the debuginfo offset.
+    direct_offset: Size,
+    /// Each offset in this vector indicates one level of indirection from the base or previous
+    /// indirect offset plus a dereference.
+    indirect_offsets: Vec<Size>,
+    /// The final location debuginfo should point to.
+    result: T,
+}
+
+fn calculate_debuginfo_offset<
+    'a,
+    'tcx,
+    Bx: BuilderMethods<'a, 'tcx>,
+    L: DebugInfoOffsetLocation<'tcx, Bx>,
+>(
+    bx: &mut Bx,
+    local: mir::Local,
+    var: &PerLocalVarDebugInfo<'tcx, Bx::DIVariable>,
+    base: L,
+) -> DebugInfoOffset<L> {
+    let mut direct_offset = Size::ZERO;
+    // FIXME(eddyb) use smallvec here.
+    let mut indirect_offsets = vec![];
+    let mut place = base;
+
+    for elem in &var.projection[..] {
+        match *elem {
+            mir::ProjectionElem::Deref => {
+                indirect_offsets.push(Size::ZERO);
+                place = place.deref(bx);
+            }
+            mir::ProjectionElem::Field(field, _) => {
+                let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset);
+                *offset += place.layout().fields.offset(field.index());
+                place = place.project_field(bx, field);
+            }
+            mir::ProjectionElem::Downcast(_, variant) => {
+                place = place.downcast(bx, variant);
+            }
+            _ => span_bug!(
+                var.source_info.span,
+                "unsupported var debuginfo place `{:?}`",
+                mir::Place { local, projection: var.projection },
+            ),
+        }
+    }
+
+    DebugInfoOffset { direct_offset, indirect_offsets, result: place }
+}
+
 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
     pub fn set_debug_loc(&self, bx: &mut Bx, source_info: mir::SourceInfo) {
         bx.set_span(source_info.span);
@@ -262,33 +362,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             let Some(dbg_var) = var.dbg_var else { continue };
             let Some(dbg_loc) = self.dbg_loc(var.source_info) else { continue };
 
-            let mut direct_offset = Size::ZERO;
-            // FIXME(eddyb) use smallvec here.
-            let mut indirect_offsets = vec![];
-            let mut place = base;
-
-            for elem in &var.projection[..] {
-                match *elem {
-                    mir::ProjectionElem::Deref => {
-                        indirect_offsets.push(Size::ZERO);
-                        place = bx.load_operand(place).deref(bx.cx());
-                    }
-                    mir::ProjectionElem::Field(field, _) => {
-                        let i = field.index();
-                        let offset = indirect_offsets.last_mut().unwrap_or(&mut direct_offset);
-                        *offset += place.layout.fields.offset(i);
-                        place = place.project_field(bx, i);
-                    }
-                    mir::ProjectionElem::Downcast(_, variant) => {
-                        place = place.project_downcast(bx, variant);
-                    }
-                    _ => span_bug!(
-                        var.source_info.span,
-                        "unsupported var debuginfo place `{:?}`",
-                        mir::Place { local, projection: var.projection },
-                    ),
-                }
-            }
+            let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
+                calculate_debuginfo_offset(bx, local, &var, base.layout);
 
             // 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
@@ -306,6 +381,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     || !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);
+
                 // Create a variable which will be a pointer to the actual value
                 let ptr_ty = bx.tcx().mk_ty(ty::RawPtr(ty::TypeAndMut {
                     mutbl: mir::Mutability::Mut,
diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs
index 86481d5d758..109161ccc83 100644
--- a/compiler/rustc_codegen_ssa/src/traits/type_.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs
@@ -122,6 +122,7 @@ pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> {
 pub trait TypeMembershipMethods<'tcx>: Backend<'tcx> {
     fn set_type_metadata(&self, function: Self::Function, typeid: String);
     fn typeid_metadata(&self, typeid: String) -> Self::Value;
+    fn set_kcfi_type_metadata(&self, function: Self::Function, typeid: u32);
 }
 
 pub trait ArgAbiMethods<'tcx>: HasCodegen<'tcx> {
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index e3dfd72d5f0..c60d6e4fed9 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -123,14 +123,14 @@ impl<'tcx> ConstEvalErr<'tcx> {
                 // Helper closure to print duplicated lines.
                 let mut flush_last_line = |last_frame, times| {
                     if let Some((line, span)) = last_frame {
-                        err.span_label(span, &line);
+                        err.span_note(span, &line);
                         // Don't print [... additional calls ...] if the number of lines is small
                         if times < 3 {
                             for _ in 0..times {
-                                err.span_label(span, &line);
+                                err.span_note(span, &line);
                             }
                         } else {
-                            err.span_label(
+                            err.span_note(
                                 span,
                                 format!("[... {} additional calls {} ...]", times, &line),
                             );
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index e17d3e516a6..0b2809f1d2c 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -17,7 +17,7 @@ use rustc_middle::ty::{
 };
 use rustc_mir_dataflow::storage::always_storage_live_locals;
 use rustc_session::Limit;
-use rustc_span::{Pos, Span};
+use rustc_span::Span;
 use rustc_target::abi::{call::FnAbi, Align, HasDataLayout, Size, TargetDataLayout};
 
 use super::{
@@ -256,25 +256,13 @@ impl<'tcx> fmt::Display for FrameInfo<'tcx> {
             if tcx.def_key(self.instance.def_id()).disambiguated_data.data
                 == DefPathData::ClosureExpr
             {
-                write!(f, "inside closure")?;
+                write!(f, "inside closure")
             } else {
                 // Note: this triggers a `good_path_bug` state, which means that if we ever get here
                 // we must emit a diagnostic. We should never display a `FrameInfo` unless we
                 // actually want to emit a warning or error to the user.
-                write!(f, "inside `{}`", self.instance)?;
+                write!(f, "inside `{}`", self.instance)
             }
-            if !self.span.is_dummy() {
-                let sm = tcx.sess.source_map();
-                let lo = sm.lookup_char_pos(self.span.lo());
-                write!(
-                    f,
-                    " at {}:{}:{}",
-                    sm.filename_for_diagnostics(&lo.file.name),
-                    lo.line,
-                    lo.col.to_usize() + 1
-                )?;
-            }
-            Ok(())
         })
     }
 }
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 88d25be6bd8..0604d5ee6fa 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -373,9 +373,21 @@ pub trait Machine<'mir, 'tcx>: Sized {
         Ok(())
     }
 
-    /// Executes a retagging operation.
+    /// Executes a retagging operation for a single pointer.
+    /// Returns the possibly adjusted pointer.
     #[inline]
-    fn retag(
+    fn retag_ptr_value(
+        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        _kind: mir::RetagKind,
+        val: &ImmTy<'tcx, Self::Provenance>,
+    ) -> InterpResult<'tcx, ImmTy<'tcx, Self::Provenance>> {
+        Ok(val.clone())
+    }
+
+    /// Executes a retagging operation on a compound value.
+    /// Replaces all pointers stored in the given place.
+    #[inline]
+    fn retag_place_contents(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _kind: mir::RetagKind,
         _place: &PlaceTy<'tcx, Self::Provenance>,
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index 60578246eed..81b44a49484 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -8,7 +8,7 @@ use rustc_middle::mir;
 use rustc_middle::mir::interpret::{InterpResult, Scalar};
 use rustc_middle::ty::layout::LayoutOf;
 
-use super::{InterpCx, Machine};
+use super::{ImmTy, InterpCx, Machine};
 
 /// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
 /// same type as the result.
@@ -108,7 +108,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             // Stacked Borrows.
             Retag(kind, place) => {
                 let dest = self.eval_place(**place)?;
-                M::retag(self, *kind, &dest)?;
+                M::retag_place_contents(self, *kind, &dest)?;
             }
 
             Intrinsic(box ref intrinsic) => self.emulate_nondiverging_intrinsic(intrinsic)?,
@@ -247,10 +247,41 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 self.write_scalar(Scalar::from_machine_usize(len, self), &dest)?;
             }
 
-            AddressOf(_, place) | Ref(_, _, place) => {
+            Ref(_, borrow_kind, place) => {
                 let src = self.eval_place(place)?;
                 let place = self.force_allocation(&src)?;
-                self.write_immediate(place.to_ref(self), &dest)?;
+                let val = ImmTy::from_immediate(place.to_ref(self), dest.layout);
+                // A fresh reference was created, make sure it gets retagged.
+                let val = M::retag_ptr_value(
+                    self,
+                    if borrow_kind.allows_two_phase_borrow() {
+                        mir::RetagKind::TwoPhase
+                    } else {
+                        mir::RetagKind::Default
+                    },
+                    &val,
+                )?;
+                self.write_immediate(*val, &dest)?;
+            }
+
+            AddressOf(_, place) => {
+                // Figure out whether this is an addr_of of an already raw place.
+                let place_base_raw = if place.has_deref() {
+                    let ty = self.frame().body.local_decls[place.local].ty;
+                    ty.is_unsafe_ptr()
+                } else {
+                    // Not a deref, and thus not raw.
+                    false
+                };
+
+                let src = self.eval_place(place)?;
+                let place = self.force_allocation(&src)?;
+                let mut val = ImmTy::from_immediate(place.to_ref(self), dest.layout);
+                if !place_base_raw {
+                    // If this was not already raw, it needs retagging.
+                    val = M::retag_ptr_value(self, mir::RetagKind::Raw, &val)?;
+                }
+                self.write_immediate(*val, &dest)?;
             }
 
             NullaryOp(null_op, ty) => {
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 57e40e168fa..0e7ffcdffc9 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -29,10 +29,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
             Goto { target } => self.go_to_block(target),
 
-            SwitchInt { ref discr, ref targets, switch_ty } => {
+            SwitchInt { ref discr, ref targets } => {
                 let discr = self.read_immediate(&self.eval_operand(discr, None)?)?;
                 trace!("SwitchInt({:?})", *discr);
-                assert_eq!(discr.layout.ty, switch_ty);
 
                 // Branch to the `otherwise` case by default, if no match is found.
                 let mut target_block = targets.otherwise();
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index bf700d31224..64318f5f54d 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -2,6 +2,7 @@
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_index::bit_set::BitSet;
+use rustc_infer::traits::Reveal;
 use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::visit::NonUseContext::VarDebugInfo;
 use rustc_middle::mir::visit::{PlaceContext, Visitor};
@@ -44,8 +45,11 @@ impl<'tcx> MirPass<'tcx> for Validator {
             return;
         }
         let def_id = body.source.def_id();
-        let param_env = tcx.param_env(def_id);
         let mir_phase = self.mir_phase;
+        let param_env = match mir_phase.reveal() {
+            Reveal::UserFacing => tcx.param_env(def_id),
+            Reveal::All => tcx.param_env_reveal_all_normalized(def_id),
+        };
 
         let always_live_locals = always_storage_live_locals(body);
         let storage_liveness = MaybeStorageLive::new(always_live_locals)
@@ -682,17 +686,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             TerminatorKind::Goto { target } => {
                 self.check_edge(location, *target, EdgeKind::Normal);
             }
-            TerminatorKind::SwitchInt { targets, switch_ty, discr } => {
-                let ty = discr.ty(&self.body.local_decls, self.tcx);
-                if ty != *switch_ty {
-                    self.fail(
-                        location,
-                        format!(
-                            "encountered `SwitchInt` terminator with type mismatch: {:?} != {:?}",
-                            ty, switch_ty,
-                        ),
-                    );
-                }
+            TerminatorKind::SwitchInt { targets, discr } => {
+                let switch_ty = discr.ty(&self.body.local_decls, self.tcx);
 
                 let target_width = self.tcx.sess.target.pointer_width;
 
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index 22f87514dd8..f06ca5a0733 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -25,6 +25,7 @@ use rustc_data_structures::sync::SeqCst;
 use rustc_errors::registry::{InvalidErrorCode, Registry};
 use rustc_errors::{ErrorGuaranteed, PResult};
 use rustc_feature::find_gated_cfg;
+use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_interface::util::{self, collect_crate_types, get_codegen_backend};
 use rustc_interface::{interface, Queries};
 use rustc_lint::LintStore;
@@ -374,14 +375,14 @@ fn run_compiler(
             queries.global_ctxt()?.peek_mut().enter(|tcx| {
                 let result = tcx.analysis(());
                 if sess.opts.unstable_opts.save_analysis {
-                    let crate_name = queries.crate_name()?.peek().clone();
+                    let crate_name = tcx.crate_name(LOCAL_CRATE);
                     sess.time("save_analysis", || {
                         save::process_crate(
                             tcx,
-                            &crate_name,
+                            crate_name,
                             compiler.input(),
                             None,
-                            DumpHandler::new(compiler.output_dir().as_deref(), &crate_name),
+                            DumpHandler::new(compiler.output_dir().as_deref(), crate_name),
                         )
                     });
                 }
@@ -678,7 +679,7 @@ fn print_crate_info(
                 let crate_types = collect_crate_types(sess, attrs);
                 for &style in &crate_types {
                     let fname =
-                        rustc_session::output::filename_for_input(sess, style, &id, &t_outputs);
+                        rustc_session::output::filename_for_input(sess, style, id, &t_outputs);
                     println!("{}", fname.file_name().unwrap().to_string_lossy());
                 }
             }
diff --git a/compiler/rustc_error_messages/locales/en-US/expand.ftl b/compiler/rustc_error_messages/locales/en-US/expand.ftl
index 5720591154f..df0e8ae5dd8 100644
--- a/compiler/rustc_error_messages/locales/en-US/expand.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/expand.ftl
@@ -20,3 +20,110 @@ expand_var_still_repeating =
     variable '{$ident}' is still repeating at this depth
 
 expand_meta_var_dif_seq_matchers = {$msg}
+
+expand_macro_const_stability =
+    macros cannot have const stability attributes
+    .label = invalid const stability attribute
+    .label2 = const stability attribute affects this macro
+
+expand_macro_body_stability =
+    macros cannot have body stability attributes
+    .label = invalid body stability attribute
+    .label2 = body stability attribute affects this macro
+
+expand_resolve_relative_path =
+    cannot resolve relative path in non-file source `{$path}`
+
+expand_attr_no_arguments =
+    attribute must have either one or two arguments
+
+expand_not_a_meta_item =
+    not a meta item
+
+expand_only_one_word =
+    must only be one word
+
+expand_cannot_be_name_of_macro =
+    `{$trait_ident}` cannot be a name of {$macro_type} macro
+
+expand_arg_not_attributes =
+    second argument must be `attributes`
+
+expand_attributes_wrong_form =
+    attribute must be of form: `attributes(foo, bar)`
+
+expand_attribute_meta_item =
+    attribute must be a meta item, not a literal
+
+expand_attribute_single_word =
+    attribute must only be a single word
+
+expand_helper_attribute_name_invalid =
+    `{$name}` cannot be a name of derive helper attribute
+
+expand_expected_comma_in_list =
+    expected token: `,`
+
+expand_only_one_argument =
+    {$name} takes 1 argument
+
+expand_takes_no_arguments =
+    {$name} takes no arguments
+
+expand_feature_included_in_edition =
+    the feature `{$feature}` is included in the Rust {$edition} edition
+
+expand_feature_removed =
+    feature has been removed
+    .label = feature has been removed
+    .reason = {$reason}
+
+expand_feature_not_allowed =
+    the feature `{$name}` is not in the list of allowed features
+
+expand_recursion_limit_reached =
+    recursion limit reached while expanding `{$descr}`
+    .help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
+
+expand_malformed_feature_attribute =
+    malformed `feature` attribute input
+    .expected = expected just one word
+
+expand_remove_expr_not_supported =
+    removing an expression is not supported in this position
+
+expand_invalid_cfg_no_parens = `cfg` is not followed by parentheses
+expand_invalid_cfg_no_predicate = `cfg` predicate is not specified
+expand_invalid_cfg_multiple_predicates = multiple `cfg` predicates are specified
+expand_invalid_cfg_predicate_literal = `cfg` predicate key cannot be a literal
+expand_invalid_cfg_expected_syntax = expected syntax is
+
+expand_wrong_fragment_kind =
+    non-{$kind} macro in {$kind} position: {$name}
+
+expand_unsupported_key_value =
+    key-value macro attributes are not supported
+
+expand_incomplete_parse =
+    macro expansion ignores token `{$token}` and any following
+    .label = caused by the macro expansion here
+    .note = the usage of `{$macro_path}!` is likely invalid in {$kind_name} context
+    .suggestion_add_semi = you might be missing a semicolon here
+
+expand_remove_node_not_supported =
+    removing {$descr} is not supported in this position
+
+expand_module_circular =
+    circular modules: {$modules}
+
+expand_module_in_block =
+    cannot declare a non-inline module inside a block unless it has a path attribute
+    .note = maybe `use` the module `{$name}` instead of redeclaring it
+
+expand_module_file_not_found =
+    file not found for module `{$name}`
+    .help = to create the module `{$name}`, create file "{$default_path}" or "{$secondary_path}"
+
+expand_module_multiple_candidates =
+    file for module `{$name}` found at both "{$default_path}" and "{$secondary_path}"
+    .help = delete or rename one of them to remove the ambiguity
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 7155db32e53..cb39e997436 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -152,6 +152,12 @@ impl IntoDiagnosticArg for ast::Path {
     }
 }
 
+impl IntoDiagnosticArg for &ast::Path {
+    fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+        DiagnosticArgValue::Str(Cow::Owned(pprust::path_to_string(self)))
+    }
+}
+
 impl IntoDiagnosticArg for ast::token::Token {
     fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
         DiagnosticArgValue::Str(pprust::token_to_string(&self))
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index db595df8ec1..4df2198fb0e 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -24,7 +24,7 @@ use rustc_lint_defs::pluralize;
 
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_data_structures::sync::Lrc;
-use rustc_error_messages::FluentArgs;
+use rustc_error_messages::{FluentArgs, SpanLabel};
 use rustc_span::hygiene::{ExpnKind, MacroKind};
 use std::borrow::Cow;
 use std::cmp::{max, min, Reverse};
@@ -773,6 +773,7 @@ impl EmitterWriter {
         draw_col_separator_no_space(buffer, line_offset, width_offset - 2);
     }
 
+    #[instrument(level = "trace", skip(self), ret)]
     fn render_source_line(
         &self,
         buffer: &mut StyledBuffer,
@@ -804,6 +805,7 @@ impl EmitterWriter {
             Some(s) => normalize_whitespace(&s),
             None => return Vec::new(),
         };
+        trace!(?source_string);
 
         let line_offset = buffer.num_lines();
 
@@ -1323,6 +1325,7 @@ impl EmitterWriter {
         }
     }
 
+    #[instrument(level = "trace", skip(self, args), ret)]
     fn emit_message_default(
         &mut self,
         msp: &MultiSpan,
@@ -1384,22 +1387,15 @@ impl EmitterWriter {
             }
         }
         let mut annotated_files = FileWithAnnotatedLines::collect_annotations(self, args, msp);
+        trace!("{annotated_files:#?}");
 
         // Make sure our primary file comes first
-        let (primary_lo, sm) = if let (Some(sm), Some(ref primary_span)) =
-            (self.sm.as_ref(), msp.primary_span().as_ref())
-        {
-            if !primary_span.is_dummy() {
-                (sm.lookup_char_pos(primary_span.lo()), sm)
-            } else {
-                emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;
-                return Ok(());
-            }
-        } else {
+        let primary_span = msp.primary_span().unwrap_or_default();
+        let (Some(sm), false) = (self.sm.as_ref(), primary_span.is_dummy()) else {
             // If we don't have span information, emit and exit
-            emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;
-            return Ok(());
+            return emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message);
         };
+        let primary_lo = sm.lookup_char_pos(primary_span.lo());
         if let Ok(pos) =
             annotated_files.binary_search_by(|x| x.file.name.cmp(&primary_lo.file.name))
         {
@@ -1410,6 +1406,54 @@ impl EmitterWriter {
         for annotated_file in annotated_files {
             // we can't annotate anything if the source is unavailable.
             if !sm.ensure_source_file_source_present(annotated_file.file.clone()) {
+                if !self.short_message {
+                    // We'll just print an unannotated message.
+                    for (annotation_id, line) in annotated_file.lines.into_iter().enumerate() {
+                        let mut annotations = line.annotations.clone();
+                        annotations.sort_by_key(|a| Reverse(a.start_col));
+                        let mut line_idx = buffer.num_lines();
+                        buffer.append(
+                            line_idx,
+                            &format!(
+                                "{}:{}:{}",
+                                sm.filename_for_diagnostics(&annotated_file.file.name),
+                                sm.doctest_offset_line(&annotated_file.file.name, line.line_index),
+                                annotations[0].start_col + 1,
+                            ),
+                            Style::LineAndColumn,
+                        );
+                        if annotation_id == 0 {
+                            buffer.prepend(line_idx, "--> ", Style::LineNumber);
+                            for _ in 0..max_line_num_len {
+                                buffer.prepend(line_idx, " ", Style::NoStyle);
+                            }
+                            line_idx += 1;
+                        };
+                        for (i, annotation) in annotations.into_iter().enumerate() {
+                            if let Some(label) = &annotation.label {
+                                let style = if annotation.is_primary {
+                                    Style::LabelPrimary
+                                } else {
+                                    Style::LabelSecondary
+                                };
+                                if annotation_id == 0 {
+                                    buffer.prepend(line_idx, " |", Style::LineNumber);
+                                    for _ in 0..max_line_num_len {
+                                        buffer.prepend(line_idx, " ", Style::NoStyle);
+                                    }
+                                    line_idx += 1;
+                                    buffer.append(line_idx + i, " = note: ", style);
+                                    for _ in 0..max_line_num_len {
+                                        buffer.prepend(line_idx, " ", Style::NoStyle);
+                                    }
+                                } else {
+                                    buffer.append(line_idx + i, ": ", style);
+                                }
+                                buffer.append(line_idx + i, label, style);
+                            }
+                        }
+                    }
+                }
                 continue;
             }
 
@@ -1656,6 +1700,7 @@ impl EmitterWriter {
                     multilines.extend(&to_add);
                 }
             }
+            trace!("buffer: {:#?}", buffer.render());
         }
 
         if let Some(tracked) = emitted_at {
@@ -1979,6 +2024,7 @@ impl EmitterWriter {
         Ok(())
     }
 
+    #[instrument(level = "trace", skip(self, args, code, children, suggestions))]
     fn emit_messages_default(
         &mut self,
         level: &Level,
@@ -2209,46 +2255,28 @@ impl FileWithAnnotatedLines {
         let mut multiline_annotations = vec![];
 
         if let Some(ref sm) = emitter.source_map() {
-            for span_label in msp.span_labels() {
-                let fixup_lo_hi = |span: Span| {
-                    let lo = sm.lookup_char_pos(span.lo());
-                    let mut hi = sm.lookup_char_pos(span.hi());
-
-                    // Watch out for "empty spans". If we get a span like 6..6, we
-                    // want to just display a `^` at 6, so convert that to
-                    // 6..7. This is degenerate input, but it's best to degrade
-                    // gracefully -- and the parser likes to supply a span like
-                    // that for EOF, in particular.
-
-                    if lo.col_display == hi.col_display && lo.line == hi.line {
-                        hi.col_display += 1;
-                    }
-                    (lo, hi)
+            for SpanLabel { span, is_primary, label } in msp.span_labels() {
+                // If we don't have a useful span, pick the primary span if that exists.
+                // Worst case we'll just print an error at the top of the main file.
+                let span = match (span.is_dummy(), msp.primary_span()) {
+                    (_, None) | (false, _) => span,
+                    (true, Some(span)) => span,
                 };
 
-                if span_label.span.is_dummy() {
-                    if let Some(span) = msp.primary_span() {
-                        // if we don't know where to render the annotation, emit it as a note
-                        // on the primary span.
-
-                        let (lo, hi) = fixup_lo_hi(span);
-
-                        let ann = Annotation {
-                            start_col: lo.col_display,
-                            end_col: hi.col_display,
-                            is_primary: span_label.is_primary,
-                            label: span_label
-                                .label
-                                .as_ref()
-                                .map(|m| emitter.translate_message(m, args).to_string()),
-                            annotation_type: AnnotationType::Singleline,
-                        };
-                        add_annotation_to_file(&mut output, lo.file, lo.line, ann);
-                    }
-                    continue;
+                let lo = sm.lookup_char_pos(span.lo());
+                let mut hi = sm.lookup_char_pos(span.hi());
+
+                // Watch out for "empty spans". If we get a span like 6..6, we
+                // want to just display a `^` at 6, so convert that to
+                // 6..7. This is degenerate input, but it's best to degrade
+                // gracefully -- and the parser likes to supply a span like
+                // that for EOF, in particular.
+
+                if lo.col_display == hi.col_display && lo.line == hi.line {
+                    hi.col_display += 1;
                 }
 
-                let (lo, hi) = fixup_lo_hi(span_label.span);
+                let label = label.as_ref().map(|m| emitter.translate_message(m, args).to_string());
 
                 if lo.line != hi.line {
                     let ml = MultilineAnnotation {
@@ -2257,11 +2285,8 @@ impl FileWithAnnotatedLines {
                         line_end: hi.line,
                         start_col: lo.col_display,
                         end_col: hi.col_display,
-                        is_primary: span_label.is_primary,
-                        label: span_label
-                            .label
-                            .as_ref()
-                            .map(|m| emitter.translate_message(m, args).to_string()),
+                        is_primary,
+                        label,
                         overlaps_exactly: false,
                     };
                     multiline_annotations.push((lo.file, ml));
@@ -2269,11 +2294,8 @@ impl FileWithAnnotatedLines {
                     let ann = Annotation {
                         start_col: lo.col_display,
                         end_col: hi.col_display,
-                        is_primary: span_label.is_primary,
-                        label: span_label
-                            .label
-                            .as_ref()
-                            .map(|m| emitter.translate_message(m, args).to_string()),
+                        is_primary,
+                        label,
                         annotation_type: AnnotationType::Singleline,
                     };
                     add_annotation_to_file(&mut output, lo.file, lo.line, ann);
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 13e2d1ebbe7..6f159663e80 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -1,3 +1,11 @@
+#![deny(rustc::untranslatable_diagnostic)]
+
+use crate::errors::{
+    ArgumentNotAttributes, AttrNoArguments, AttributeMetaItem, AttributeSingleWord,
+    AttributesWrongForm, CannotBeNameOfMacro, ExpectedCommaInList, HelperAttributeNameInvalid,
+    MacroBodyStability, MacroConstStability, NotAMetaItem, OnlyOneArgument, OnlyOneWord,
+    ResolveRelativePath, TakesNoArguments,
+};
 use crate::expand::{self, AstFragment, Invocation};
 use crate::module::DirOwnership;
 
@@ -789,26 +797,16 @@ impl SyntaxExtension {
             .unwrap_or_else(|| (None, helper_attrs));
         let (stability, const_stability, body_stability) = attr::find_stability(&sess, attrs, span);
         if let Some((_, sp)) = const_stability {
-            sess.parse_sess
-                .span_diagnostic
-                .struct_span_err(sp, "macros cannot have const stability attributes")
-                .span_label(sp, "invalid const stability attribute")
-                .span_label(
-                    sess.source_map().guess_head_span(span),
-                    "const stability attribute affects this macro",
-                )
-                .emit();
+            sess.emit_err(MacroConstStability {
+                span: sp,
+                head_span: sess.source_map().guess_head_span(span),
+            });
         }
         if let Some((_, sp)) = body_stability {
-            sess.parse_sess
-                .span_diagnostic
-                .struct_span_err(sp, "macros cannot have body stability attributes")
-                .span_label(sp, "invalid body stability attribute")
-                .span_label(
-                    sess.source_map().guess_head_span(span),
-                    "body stability attribute affects this macro",
-                )
-                .emit();
+            sess.emit_err(MacroBodyStability {
+                span: sp,
+                head_span: sess.source_map().guess_head_span(span),
+            });
         }
 
         SyntaxExtension {
@@ -960,7 +958,7 @@ pub trait LintStoreExpand {
         node_id: NodeId,
         attrs: &[Attribute],
         items: &[P<Item>],
-        name: &str,
+        name: Symbol,
     );
 }
 
@@ -1200,13 +1198,11 @@ pub fn resolve_path(
                 .expect("attempting to resolve a file path in an external file"),
             FileName::DocTest(path, _) => path,
             other => {
-                return Err(parse_sess.span_diagnostic.struct_span_err(
+                return Err(ResolveRelativePath {
                     span,
-                    &format!(
-                        "cannot resolve relative path in non-file source `{}`",
-                        parse_sess.source_map().filename_for_diagnostics(&other)
-                    ),
-                ));
+                    path: parse_sess.source_map().filename_for_diagnostics(&other).to_string(),
+                }
+                .into_diagnostic(&parse_sess.span_diagnostic));
             }
         };
         result.pop();
@@ -1222,6 +1218,8 @@ pub fn resolve_path(
 /// The returned bool indicates whether an applicable suggestion has already been
 /// added to the diagnostic to avoid emitting multiple suggestions. `Err(None)`
 /// indicates that an ast error was encountered.
+// FIXME(Nilstrieb) Make this function setup translatable
+#[allow(rustc::untranslatable_diagnostic)]
 pub fn expr_to_spanned_string<'a>(
     cx: &'a mut ExtCtxt<'_>,
     expr: P<ast::Expr>,
@@ -1280,9 +1278,9 @@ pub fn expr_to_string(
 /// compilation should call
 /// `cx.parse_sess.span_diagnostic.abort_if_errors()` (this should be
 /// done as rarely as possible).
-pub fn check_zero_tts(cx: &ExtCtxt<'_>, sp: Span, tts: TokenStream, name: &str) {
+pub fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, name: &str) {
     if !tts.is_empty() {
-        cx.span_err(sp, &format!("{} takes no arguments", name));
+        cx.emit_err(TakesNoArguments { span, name });
     }
 }
 
@@ -1304,31 +1302,27 @@ pub fn parse_expr(p: &mut parser::Parser<'_>) -> Option<P<ast::Expr>> {
 /// expect exactly one string literal, or emit an error and return `None`.
 pub fn get_single_str_from_tts(
     cx: &mut ExtCtxt<'_>,
-    sp: Span,
+    span: Span,
     tts: TokenStream,
     name: &str,
 ) -> Option<Symbol> {
     let mut p = cx.new_parser_from_tts(tts);
     if p.token == token::Eof {
-        cx.span_err(sp, &format!("{} takes 1 argument", name));
+        cx.emit_err(OnlyOneArgument { span, name });
         return None;
     }
     let ret = parse_expr(&mut p)?;
     let _ = p.eat(&token::Comma);
 
     if p.token != token::Eof {
-        cx.span_err(sp, &format!("{} takes 1 argument", name));
+        cx.emit_err(OnlyOneArgument { span, name });
     }
     expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s)
 }
 
 /// Extracts comma-separated expressions from `tts`.
 /// On error, emit it, and return `None`.
-pub fn get_exprs_from_tts(
-    cx: &mut ExtCtxt<'_>,
-    sp: Span,
-    tts: TokenStream,
-) -> Option<Vec<P<ast::Expr>>> {
+pub fn get_exprs_from_tts(cx: &mut ExtCtxt<'_>, tts: TokenStream) -> Option<Vec<P<ast::Expr>>> {
     let mut p = cx.new_parser_from_tts(tts);
     let mut es = Vec::new();
     while p.token != token::Eof {
@@ -1343,7 +1337,7 @@ pub fn get_exprs_from_tts(
             continue;
         }
         if p.token != token::Eof {
-            cx.span_err(sp, "expected token: `,`");
+            cx.emit_err(ExpectedCommaInList { span: p.token.span });
             return None;
         }
     }
@@ -1353,64 +1347,58 @@ pub fn get_exprs_from_tts(
 pub fn parse_macro_name_and_helper_attrs(
     diag: &rustc_errors::Handler,
     attr: &Attribute,
-    descr: &str,
+    macro_type: &str,
 ) -> Option<(Symbol, Vec<Symbol>)> {
     // Once we've located the `#[proc_macro_derive]` attribute, verify
     // that it's of the form `#[proc_macro_derive(Foo)]` or
     // `#[proc_macro_derive(Foo, attributes(A, ..))]`
     let list = attr.meta_item_list()?;
     if list.len() != 1 && list.len() != 2 {
-        diag.span_err(attr.span, "attribute must have either one or two arguments");
+        diag.emit_err(AttrNoArguments { span: attr.span });
         return None;
     }
     let Some(trait_attr) = list[0].meta_item() else {
-        diag.span_err(list[0].span(), "not a meta item");
+        diag.emit_err(NotAMetaItem {span: list[0].span()});
         return None;
     };
     let trait_ident = match trait_attr.ident() {
         Some(trait_ident) if trait_attr.is_word() => trait_ident,
         _ => {
-            diag.span_err(trait_attr.span, "must only be one word");
+            diag.emit_err(OnlyOneWord { span: trait_attr.span });
             return None;
         }
     };
 
     if !trait_ident.name.can_be_raw() {
-        diag.span_err(
-            trait_attr.span,
-            &format!("`{}` cannot be a name of {} macro", trait_ident, descr),
-        );
+        diag.emit_err(CannotBeNameOfMacro { span: trait_attr.span, trait_ident, macro_type });
     }
 
     let attributes_attr = list.get(1);
     let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
         if !attr.has_name(sym::attributes) {
-            diag.span_err(attr.span(), "second argument must be `attributes`");
+            diag.emit_err(ArgumentNotAttributes { span: attr.span() });
         }
         attr.meta_item_list()
             .unwrap_or_else(|| {
-                diag.span_err(attr.span(), "attribute must be of form: `attributes(foo, bar)`");
+                diag.emit_err(AttributesWrongForm { span: attr.span() });
                 &[]
             })
             .iter()
             .filter_map(|attr| {
                 let Some(attr) = attr.meta_item() else {
-                    diag.span_err(attr.span(), "not a meta item");
+                    diag.emit_err(AttributeMetaItem { span: attr.span() });
                     return None;
                 };
 
                 let ident = match attr.ident() {
                     Some(ident) if attr.is_word() => ident,
                     _ => {
-                        diag.span_err(attr.span, "must only be one word");
+                        diag.emit_err(AttributeSingleWord { span: attr.span });
                         return None;
                     }
                 };
                 if !ident.name.can_be_raw() {
-                    diag.span_err(
-                        attr.span,
-                        &format!("`{}` cannot be a name of derive helper attribute", ident),
-                    );
+                    diag.emit_err(HelperAttributeNameInvalid { span: attr.span, name: ident });
                 }
 
                 Some(ident.name)
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 2510795c2e3..f4c6f3386ad 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -1,5 +1,9 @@
 //! Conditional compilation stripping.
 
+use crate::errors::{
+    FeatureIncludedInEdition, FeatureNotAllowed, FeatureRemoved, FeatureRemovedReason, InvalidCfg,
+    MalformedFeatureAttribute, MalformedFeatureAttributeHelp, RemoveExprNotSupported,
+};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{Delimiter, Token, TokenKind};
 use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree};
@@ -10,7 +14,6 @@ use rustc_ast::{self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem
 use rustc_attr as attr;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::map_in_place::MapInPlace;
-use rustc_errors::{error_code, struct_span_err, Applicability, Handler};
 use rustc_feature::{Feature, Features, State as FeatureState};
 use rustc_feature::{
     ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
@@ -33,18 +36,12 @@ pub struct StripUnconfigured<'a> {
     pub lint_node_id: NodeId,
 }
 
-fn get_features(
-    sess: &Session,
-    span_handler: &Handler,
-    krate_attrs: &[ast::Attribute],
-) -> Features {
-    fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
-        let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
-        err.span_label(span, "feature has been removed");
-        if let Some(reason) = reason {
-            err.note(reason);
-        }
-        err.emit();
+fn get_features(sess: &Session, krate_attrs: &[ast::Attribute]) -> Features {
+    fn feature_removed(sess: &Session, span: Span, reason: Option<&str>) {
+        sess.emit_err(FeatureRemoved {
+            span,
+            reason: reason.map(|reason| FeatureRemovedReason { reason }),
+        });
     }
 
     fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feature> {
@@ -117,34 +114,34 @@ fn get_features(
             continue;
         };
 
-        let bad_input = |span| {
-            struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input")
-        };
-
         for mi in list {
             let name = match mi.ident() {
                 Some(ident) if mi.is_word() => ident.name,
                 Some(ident) => {
-                    bad_input(mi.span())
-                        .span_suggestion(
-                            mi.span(),
-                            "expected just one word",
-                            ident.name,
-                            Applicability::MaybeIncorrect,
-                        )
-                        .emit();
+                    sess.emit_err(MalformedFeatureAttribute {
+                        span: mi.span(),
+                        help: MalformedFeatureAttributeHelp::Suggestion {
+                            span: mi.span(),
+                            suggestion: ident.name,
+                        },
+                    });
                     continue;
                 }
                 None => {
-                    bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit();
+                    sess.emit_err(MalformedFeatureAttribute {
+                        span: mi.span(),
+                        help: MalformedFeatureAttributeHelp::Label { span: mi.span() },
+                    });
                     continue;
                 }
             };
 
-            if let Some(edition) = edition_enabled_features.get(&name) {
-                let msg =
-                    &format!("the feature `{}` is included in the Rust {} edition", name, edition);
-                span_handler.struct_span_warn_with_code(mi.span(), msg, error_code!(E0705)).emit();
+            if let Some(&edition) = edition_enabled_features.get(&name) {
+                sess.emit_warning(FeatureIncludedInEdition {
+                    span: mi.span(),
+                    feature: name,
+                    edition,
+                });
                 continue;
             }
 
@@ -159,7 +156,7 @@ fn get_features(
                 if let FeatureState::Removed { reason } | FeatureState::Stabilized { reason } =
                     state
                 {
-                    feature_removed(span_handler, mi.span(), *reason);
+                    feature_removed(sess, mi.span(), *reason);
                     continue;
                 }
             }
@@ -173,14 +170,7 @@ fn get_features(
 
             if let Some(allowed) = sess.opts.unstable_opts.allow_features.as_ref() {
                 if allowed.iter().all(|f| name.as_str() != f) {
-                    struct_span_err!(
-                        span_handler,
-                        mi.span(),
-                        E0725,
-                        "the feature `{}` is not in the list of allowed features",
-                        name
-                    )
-                    .emit();
+                    sess.emit_err(FeatureNotAllowed { span: mi.span(), name });
                     continue;
                 }
             }
@@ -221,7 +211,7 @@ pub fn features(
         }
         Some(attrs) => {
             krate.attrs = attrs;
-            let features = get_features(sess, diag, &krate.attrs);
+            let features = get_features(sess, &krate.attrs);
             if err_count == diag.err_count() {
                 // Avoid reconfiguring malformed `cfg_attr`s.
                 strip_unconfigured.features = Some(&features);
@@ -503,8 +493,7 @@ impl<'a> StripUnconfigured<'a> {
         // N.B., this is intentionally not part of the visit_expr() function
         //     in order for filter_map_expr() to be able to avoid this check
         if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(*a)) {
-            let msg = "removing an expression is not supported in this position";
-            self.sess.parse_sess.span_diagnostic.span_err(attr.span, msg);
+            self.sess.emit_err(RemoveExprNotSupported { span: attr.span });
         }
 
         self.process_cfg_attrs(expr);
@@ -513,27 +502,26 @@ impl<'a> StripUnconfigured<'a> {
 }
 
 pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a MetaItem> {
-    let error = |span, msg, suggestion: &str| {
-        let mut err = sess.parse_sess.span_diagnostic.struct_span_err(span, msg);
-        if !suggestion.is_empty() {
-            err.span_suggestion(
-                span,
-                "expected syntax is",
-                suggestion,
-                Applicability::HasPlaceholders,
-            );
-        }
-        err.emit();
-        None
-    };
     let span = meta_item.span;
     match meta_item.meta_item_list() {
-        None => error(span, "`cfg` is not followed by parentheses", "cfg(/* predicate */)"),
-        Some([]) => error(span, "`cfg` predicate is not specified", ""),
-        Some([_, .., l]) => error(l.span(), "multiple `cfg` predicates are specified", ""),
+        None => {
+            sess.emit_err(InvalidCfg::NotFollowedByParens { span });
+            None
+        }
+        Some([]) => {
+            sess.emit_err(InvalidCfg::NoPredicate { span });
+            None
+        }
+        Some([_, .., l]) => {
+            sess.emit_err(InvalidCfg::MultiplePredicates { span: l.span() });
+            None
+        }
         Some([single]) => match single.meta_item() {
             Some(meta_item) => Some(meta_item),
-            None => error(single.span(), "`cfg` predicate key cannot be a literal", ""),
+            None => {
+                sess.emit_err(InvalidCfg::PredicateLiteral { span: single.span() });
+                None
+            }
         },
     }
 }
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index d383f4832f6..afe5169d3f5 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -1,6 +1,10 @@
+use rustc_ast::ast;
 use rustc_macros::Diagnostic;
-use rustc_span::symbol::MacroRulesNormalizedIdent;
-use rustc_span::Span;
+use rustc_session::Limit;
+use rustc_span::edition::Edition;
+use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent};
+use rustc_span::{Span, Symbol};
+use std::borrow::Cow;
 
 #[derive(Diagnostic)]
 #[diag(expand_expr_repeat_no_syntax_vars)]
@@ -46,3 +50,321 @@ pub(crate) struct MetaVarsDifSeqMatchers {
     pub span: Span,
     pub msg: String,
 }
+
+#[derive(Diagnostic)]
+#[diag(expand_resolve_relative_path)]
+pub(crate) struct ResolveRelativePath {
+    #[primary_span]
+    pub span: Span,
+    pub path: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_macro_const_stability)]
+pub(crate) struct MacroConstStability {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    #[label(label2)]
+    pub head_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_macro_body_stability)]
+pub(crate) struct MacroBodyStability {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    #[label(label2)]
+    pub head_span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_attr_no_arguments)]
+pub(crate) struct AttrNoArguments {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_not_a_meta_item)]
+pub(crate) struct NotAMetaItem {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_only_one_word)]
+pub(crate) struct OnlyOneWord {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_cannot_be_name_of_macro)]
+pub(crate) struct CannotBeNameOfMacro<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub trait_ident: Ident,
+    pub macro_type: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_arg_not_attributes)]
+pub(crate) struct ArgumentNotAttributes {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_attributes_wrong_form)]
+pub(crate) struct AttributesWrongForm {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_attribute_meta_item)]
+pub(crate) struct AttributeMetaItem {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_attribute_single_word)]
+pub(crate) struct AttributeSingleWord {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_helper_attribute_name_invalid)]
+pub(crate) struct HelperAttributeNameInvalid {
+    #[primary_span]
+    pub span: Span,
+    pub name: Ident,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_expected_comma_in_list)]
+pub(crate) struct ExpectedCommaInList {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_only_one_argument)]
+pub(crate) struct OnlyOneArgument<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_takes_no_arguments)]
+pub(crate) struct TakesNoArguments<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub name: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_feature_included_in_edition, code = "E0705")]
+pub(crate) struct FeatureIncludedInEdition {
+    #[primary_span]
+    pub span: Span,
+    pub feature: Symbol,
+    pub edition: Edition,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_feature_removed, code = "E0557")]
+pub(crate) struct FeatureRemoved<'a> {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    #[subdiagnostic]
+    pub reason: Option<FeatureRemovedReason<'a>>,
+}
+
+#[derive(Subdiagnostic)]
+#[note(reason)]
+pub(crate) struct FeatureRemovedReason<'a> {
+    pub reason: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_feature_not_allowed, code = "E0725")]
+pub(crate) struct FeatureNotAllowed {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_recursion_limit_reached)]
+#[help]
+pub(crate) struct RecursionLimitReached<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub descr: String,
+    pub suggested_limit: Limit,
+    pub crate_name: &'a str,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_malformed_feature_attribute, code = "E0556")]
+pub(crate) struct MalformedFeatureAttribute {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub help: MalformedFeatureAttributeHelp,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum MalformedFeatureAttributeHelp {
+    #[label(expected)]
+    Label {
+        #[primary_span]
+        span: Span,
+    },
+    #[suggestion(expected, code = "{suggestion}", applicability = "maybe-incorrect")]
+    Suggestion {
+        #[primary_span]
+        span: Span,
+        suggestion: Symbol,
+    },
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_remove_expr_not_supported)]
+pub(crate) struct RemoveExprNotSupported {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+pub(crate) enum InvalidCfg {
+    #[diag(expand_invalid_cfg_no_parens)]
+    NotFollowedByParens {
+        #[primary_span]
+        #[suggestion(
+            expand_invalid_cfg_expected_syntax,
+            code = "cfg(/* predicate */)",
+            applicability = "has-placeholders"
+        )]
+        span: Span,
+    },
+    #[diag(expand_invalid_cfg_no_predicate)]
+    NoPredicate {
+        #[primary_span]
+        #[suggestion(
+            expand_invalid_cfg_expected_syntax,
+            code = "cfg(/* predicate */)",
+            applicability = "has-placeholders"
+        )]
+        span: Span,
+    },
+    #[diag(expand_invalid_cfg_multiple_predicates)]
+    MultiplePredicates {
+        #[primary_span]
+        span: Span,
+    },
+    #[diag(expand_invalid_cfg_predicate_literal)]
+    PredicateLiteral {
+        #[primary_span]
+        span: Span,
+    },
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_wrong_fragment_kind)]
+pub(crate) struct WrongFragmentKind<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub kind: &'a str,
+    pub name: &'a ast::Path,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_unsupported_key_value)]
+pub(crate) struct UnsupportedKeyValue {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_incomplete_parse)]
+#[note]
+pub(crate) struct IncompleteParse<'a> {
+    #[primary_span]
+    pub span: Span,
+    pub token: Cow<'a, str>,
+    #[label]
+    pub label_span: Span,
+    pub macro_path: &'a ast::Path,
+    pub kind_name: &'a str,
+
+    #[suggestion(
+        suggestion_add_semi,
+        style = "verbose",
+        code = ";",
+        applicability = "maybe-incorrect"
+    )]
+    pub add_semicolon: Option<Span>,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_remove_node_not_supported)]
+pub(crate) struct RemoveNodeNotSupported {
+    #[primary_span]
+    pub span: Span,
+    pub descr: &'static str,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_module_circular)]
+pub(crate) struct ModuleCircular {
+    #[primary_span]
+    pub span: Span,
+    pub modules: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_module_in_block)]
+pub(crate) struct ModuleInBlock {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub name: Option<ModuleInBlockName>,
+}
+
+#[derive(Subdiagnostic)]
+#[note(note)]
+pub(crate) struct ModuleInBlockName {
+    #[primary_span]
+    pub span: Span,
+    pub name: Ident,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_module_file_not_found, code = "E0583")]
+#[help]
+pub(crate) struct ModuleFileNotFound {
+    #[primary_span]
+    pub span: Span,
+    pub name: Ident,
+    pub default_path: String,
+    pub secondary_path: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(expand_module_multiple_candidates, code = "E0761")]
+#[help]
+pub(crate) struct ModuleMultipleCandidates {
+    #[primary_span]
+    pub span: Span,
+    pub name: Ident,
+    pub default_path: String,
+    pub secondary_path: String,
+}
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index e799fa404f6..e26c16dcd7e 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -1,5 +1,9 @@
 use crate::base::*;
 use crate::config::StripUnconfigured;
+use crate::errors::{
+    IncompleteParse, RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported,
+    UnsupportedKeyValue, WrongFragmentKind,
+};
 use crate::hygiene::SyntaxContext;
 use crate::mbe::diagnostics::annotate_err_with_kind;
 use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod};
@@ -18,7 +22,7 @@ use rustc_ast::{NestedMetaItem, NodeId, PatKind, StmtKind, TyKind};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::map_in_place::MapInPlace;
 use rustc_data_structures::sync::Lrc;
-use rustc_errors::{Applicability, PResult};
+use rustc_errors::PResult;
 use rustc_feature::Features;
 use rustc_parse::parser::{
     AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, RecoverColon, RecoverComma,
@@ -606,29 +610,22 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             Limit(0) => Limit(2),
             limit => limit * 2,
         };
-        self.cx
-            .struct_span_err(
-                expn_data.call_site,
-                &format!("recursion limit reached while expanding `{}`", expn_data.kind.descr()),
-            )
-            .help(&format!(
-                "consider increasing the recursion limit by adding a \
-                 `#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
-                suggested_limit, self.cx.ecfg.crate_name,
-            ))
-            .emit();
+
+        self.cx.emit_err(RecursionLimitReached {
+            span: expn_data.call_site,
+            descr: expn_data.kind.descr(),
+            suggested_limit,
+            crate_name: &self.cx.ecfg.crate_name,
+        });
+
         self.cx.trace_macros_diag();
     }
 
     /// A macro's expansion does not fit in this fragment kind.
     /// For example, a non-type macro in a type position.
     fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::MacCall, span: Span) {
-        let msg = format!(
-            "non-{kind} macro in {kind} position: {path}",
-            kind = kind.name(),
-            path = pprust::path_to_string(&mac.path),
-        );
-        self.cx.span_err(span, &msg);
+        self.cx.emit_err(WrongFragmentKind { span, kind: kind.name(), name: &mac.path });
+
         self.cx.trace_macros_diag();
     }
 
@@ -707,7 +704,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                     };
                     let attr_item = attr.unwrap_normal_item();
                     if let AttrArgs::Eq(..) = attr_item.args {
-                        self.cx.span_err(span, "key-value macro attributes are not supported");
+                        self.cx.emit_err(UnsupportedKeyValue { span });
                     }
                     let inner_tokens = attr_item.args.inner_tokens();
                     let Ok(tok_result) = expander.expand(self.cx, span, inner_tokens, tokens) else {
@@ -729,9 +726,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                                 }
                             };
                             if fragment_kind == AstFragmentKind::Expr && items.is_empty() {
-                                let msg =
-                                    "removing an expression is not supported in this position";
-                                self.cx.span_err(span, msg);
+                                self.cx.emit_err(RemoveExprNotSupported { span });
                                 fragment_kind.dummy(span)
                             } else {
                                 fragment_kind.expect_from_annotatables(items)
@@ -939,38 +934,32 @@ pub fn parse_ast_fragment<'a>(
 }
 
 pub fn ensure_complete_parse<'a>(
-    this: &mut Parser<'a>,
+    parser: &mut Parser<'a>,
     macro_path: &ast::Path,
     kind_name: &str,
     span: Span,
 ) {
-    if this.token != token::Eof {
-        let token = pprust::token_to_string(&this.token);
-        let msg = format!("macro expansion ignores token `{}` and any following", token);
+    if parser.token != token::Eof {
+        let token = pprust::token_to_string(&parser.token);
         // Avoid emitting backtrace info twice.
-        let def_site_span = this.token.span.with_ctxt(SyntaxContext::root());
-        let mut err = this.struct_span_err(def_site_span, &msg);
-        err.span_label(span, "caused by the macro expansion here");
-        let msg = format!(
-            "the usage of `{}!` is likely invalid in {} context",
-            pprust::path_to_string(macro_path),
-            kind_name,
-        );
-        err.note(&msg);
+        let def_site_span = parser.token.span.with_ctxt(SyntaxContext::root());
 
-        let semi_span = this.sess.source_map().next_point(span);
-        match this.sess.source_map().span_to_snippet(semi_span) {
+        let semi_span = parser.sess.source_map().next_point(span);
+        let add_semicolon = match parser.sess.source_map().span_to_snippet(semi_span) {
             Ok(ref snippet) if &snippet[..] != ";" && kind_name == "expression" => {
-                err.span_suggestion(
-                    span.shrink_to_hi(),
-                    "you might be missing a semicolon here",
-                    ";",
-                    Applicability::MaybeIncorrect,
-                );
+                Some(span.shrink_to_hi())
             }
-            _ => {}
-        }
-        err.emit();
+            _ => None,
+        };
+
+        parser.sess.emit_err(IncompleteParse {
+            span: def_site_span,
+            token,
+            label_span: span,
+            macro_path,
+            kind_name,
+            add_semicolon,
+        });
     }
 }
 
@@ -1122,7 +1111,7 @@ impl InvocationCollectorNode for P<ast::Item> {
                         ecx.current_expansion.lint_node_id,
                         &attrs,
                         &items,
-                        ident.name.as_str(),
+                        ident.name,
                     );
                 }
 
@@ -1766,9 +1755,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                         if self.expand_cfg_true(node, attr, pos) {
                             continue;
                         }
-                        let msg =
-                            format!("removing {} is not supported in this position", Node::descr());
-                        self.cx.span_err(span, &msg);
+
+                        self.cx.emit_err(RemoveNodeNotSupported { span, descr: Node::descr() });
                         continue;
                     }
                     sym::cfg_attr => {
diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs
index b34de94fb7d..89726856635 100644
--- a/compiler/rustc_expand/src/lib.rs
+++ b/compiler/rustc_expand/src/lib.rs
@@ -10,6 +10,7 @@
 #![feature(rustc_attrs)]
 #![feature(try_blocks)]
 #![recursion_limit = "256"]
+#![deny(rustc::untranslatable_diagnostic)]
 
 #[macro_use]
 extern crate rustc_macros;
@@ -31,8 +32,13 @@ pub mod config;
 pub mod errors;
 pub mod expand;
 pub mod module;
+
+// FIXME(Nilstrieb) Translate proc_macro diagnostics
+#[allow(rustc::untranslatable_diagnostic)]
 pub mod proc_macro;
 
+// FIXME(Nilstrieb) Translate macro_rules diagnostics
+#[allow(rustc::untranslatable_diagnostic)]
 pub(crate) mod mbe;
 
 // HACK(Centril, #64197): These shouldn't really be here.
diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs
index 9002a24e42f..07f47a9c3a4 100644
--- a/compiler/rustc_expand/src/module.rs
+++ b/compiler/rustc_expand/src/module.rs
@@ -1,13 +1,17 @@
 use crate::base::ModuleData;
+use crate::errors::{
+    ModuleCircular, ModuleFileNotFound, ModuleInBlock, ModuleInBlockName, ModuleMultipleCandidates,
+};
 use rustc_ast::ptr::P;
 use rustc_ast::{token, AttrVec, Attribute, Inline, Item, ModSpans};
-use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorGuaranteed};
+use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
 use rustc_parse::new_parser_from_file;
 use rustc_parse::validate_attr;
 use rustc_session::parse::ParseSess;
 use rustc_session::Session;
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
+use std::iter::once;
 
 use std::path::{self, Path, PathBuf};
 
@@ -242,57 +246,41 @@ pub fn default_submod_path<'a>(
 
 impl ModError<'_> {
     fn report(self, sess: &Session, span: Span) -> ErrorGuaranteed {
-        let diag = &sess.parse_sess.span_diagnostic;
         match self {
             ModError::CircularInclusion(file_paths) => {
-                let mut msg = String::from("circular modules: ");
-                for file_path in &file_paths {
-                    msg.push_str(&file_path.display().to_string());
-                    msg.push_str(" -> ");
-                }
-                msg.push_str(&file_paths[0].display().to_string());
-                diag.struct_span_err(span, &msg)
-            }
-            ModError::ModInBlock(ident) => {
-                let msg = "cannot declare a non-inline module inside a block unless it has a path attribute";
-                let mut err = diag.struct_span_err(span, msg);
-                if let Some(ident) = ident {
-                    let note =
-                        format!("maybe `use` the module `{}` instead of redeclaring it", ident);
-                    err.span_note(span, &note);
-                }
-                err
+                let path_to_string = |path: &PathBuf| path.display().to_string();
+
+                let paths = file_paths
+                    .iter()
+                    .map(path_to_string)
+                    .chain(once(path_to_string(&file_paths[0])))
+                    .collect::<Vec<_>>();
+
+                let modules = paths.join(" -> ");
+
+                sess.emit_err(ModuleCircular { span, modules })
             }
-            ModError::FileNotFound(ident, default_path, secondary_path) => {
-                let mut err = struct_span_err!(
-                    diag,
+            ModError::ModInBlock(ident) => sess.emit_err(ModuleInBlock {
+                span,
+                name: ident.map(|name| ModuleInBlockName { span, name }),
+            }),
+            ModError::FileNotFound(name, default_path, secondary_path) => {
+                sess.emit_err(ModuleFileNotFound {
                     span,
-                    E0583,
-                    "file not found for module `{}`",
-                    ident,
-                );
-                err.help(&format!(
-                    "to create the module `{}`, create file \"{}\" or \"{}\"",
-                    ident,
-                    default_path.display(),
-                    secondary_path.display(),
-                ));
-                err
+                    name,
+                    default_path: default_path.display().to_string(),
+                    secondary_path: secondary_path.display().to_string(),
+                })
             }
-            ModError::MultipleCandidates(ident, default_path, secondary_path) => {
-                let mut err = struct_span_err!(
-                    diag,
+            ModError::MultipleCandidates(name, default_path, secondary_path) => {
+                sess.emit_err(ModuleMultipleCandidates {
                     span,
-                    E0761,
-                    "file for module `{}` found at both \"{}\" and \"{}\"",
-                    ident,
-                    default_path.display(),
-                    secondary_path.display(),
-                );
-                err.help("delete or rename one of them to remove the ambiguity");
-                err
+                    name,
+                    default_path: default_path.display().to_string(),
+                    secondary_path: secondary_path.display().to_string(),
+                })
             }
-            ModError::ParserError(err) => err,
-        }.emit()
+            ModError::ParserError(mut err) => err.emit(),
+        }
     }
 }
diff --git a/compiler/rustc_expand/src/tests.rs b/compiler/rustc_expand/src/tests.rs
index 539b04535a0..8f3bea29ffd 100644
--- a/compiler/rustc_expand/src/tests.rs
+++ b/compiler/rustc_expand/src/tests.rs
@@ -154,6 +154,7 @@ fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &
             false,
         );
         let handler = Handler::with_emitter(true, None, Box::new(emitter));
+        #[allow(rustc::untranslatable_diagnostic)]
         handler.span_err(msp, "foo");
 
         assert!(
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 4b6e068db43..6d8e78a0f18 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -394,7 +394,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ungated!(instruction_set, Normal, template!(List: "set"), ErrorPreceding),
     gated!(
         no_sanitize, Normal,
-        template!(List: "address, memory, thread"), DuplicatesOk,
+        template!(List: "address, kcfi, memory, thread"), DuplicatesOk,
         experimental!(no_sanitize)
     ),
     gated!(no_coverage, Normal, template!(Word), WarnFollowing, experimental!(no_coverage)),
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 636e6e1b48d..8bc022e1e17 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -827,7 +827,7 @@ impl<'tcx> AttributeMap<'tcx> {
 pub struct OwnerNodes<'tcx> {
     /// Pre-computed hash of the full HIR.
     pub hash_including_bodies: Fingerprint,
-    /// Pre-computed hash of the item signature, sithout recursing into the body.
+    /// Pre-computed hash of the item signature, without recursing into the body.
     pub hash_without_bodies: Fingerprint,
     /// Full HIR for the current owner.
     // The zeroth node's parent should never be accessed: the owner's parent is computed by the
diff --git a/compiler/rustc_hir/src/tests.rs b/compiler/rustc_hir/src/tests.rs
index 4636d515249..d4791150947 100644
--- a/compiler/rustc_hir/src/tests.rs
+++ b/compiler/rustc_hir/src/tests.rs
@@ -1,5 +1,7 @@
 use crate::definitions::{DefKey, DefPathData, DisambiguatedDefPathData};
 use rustc_span::def_id::{DefPathHash, StableCrateId};
+use rustc_span::edition::Edition;
+use rustc_span::{create_session_if_not_set_then, Symbol};
 
 #[test]
 fn def_path_hash_depends_on_crate_id() {
@@ -11,26 +13,28 @@ fn def_path_hash_depends_on_crate_id() {
     // the crate by changing the crate disambiguator (e.g. via bumping the
     // crate's version number).
 
-    let id0 = StableCrateId::new("foo", false, vec!["1".to_string()]);
-    let id1 = StableCrateId::new("foo", false, vec!["2".to_string()]);
+    create_session_if_not_set_then(Edition::Edition2024, |_| {
+        let id0 = StableCrateId::new(Symbol::intern("foo"), false, vec!["1".to_string()]);
+        let id1 = StableCrateId::new(Symbol::intern("foo"), false, vec!["2".to_string()]);
 
-    let h0 = mk_test_hash(id0);
-    let h1 = mk_test_hash(id1);
+        let h0 = mk_test_hash(id0);
+        let h1 = mk_test_hash(id1);
 
-    assert_ne!(h0.stable_crate_id(), h1.stable_crate_id());
-    assert_ne!(h0.local_hash(), h1.local_hash());
+        assert_ne!(h0.stable_crate_id(), h1.stable_crate_id());
+        assert_ne!(h0.local_hash(), h1.local_hash());
 
-    fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash {
-        let parent_hash = DefPathHash::new(stable_crate_id, 0);
+        fn mk_test_hash(stable_crate_id: StableCrateId) -> DefPathHash {
+            let parent_hash = DefPathHash::new(stable_crate_id, 0);
 
-        let key = DefKey {
-            parent: None,
-            disambiguated_data: DisambiguatedDefPathData {
-                data: DefPathData::CrateRoot,
-                disambiguator: 0,
-            },
-        };
+            let key = DefKey {
+                parent: None,
+                disambiguated_data: DisambiguatedDefPathData {
+                    data: DefPathData::CrateRoot,
+                    disambiguator: 0,
+                },
+            };
 
-        key.compute_stable_hash(parent_hash)
-    }
+            key.compute_stable_hash(parent_hash)
+        }
+    })
 }
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 945361ef43a..72288e5bc76 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -955,7 +955,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
                     .struct_span_err(
                         attr.span,
                         "the `#[rustc_must_implement_one_of]` attribute must be \
-                        used with at least 2 args",
+                         used with at least 2 args",
                     )
                     .emit();
 
@@ -987,7 +987,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
                             tcx.sess
                                 .struct_span_err(
                                     item.span,
-                                    "This function doesn't have a default implementation",
+                                    "function doesn't have a default implementation",
                                 )
                                 .span_note(attr_span, "required by this annotation")
                                 .emit();
@@ -999,17 +999,17 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
                     }
                     Some(item) => {
                         tcx.sess
-                            .struct_span_err(item.span, "Not a function")
+                            .struct_span_err(item.span, "not a function")
                             .span_note(attr_span, "required by this annotation")
                             .note(
-                                "All `#[rustc_must_implement_one_of]` arguments \
-                            must be associated function names",
+                                "all `#[rustc_must_implement_one_of]` arguments must be associated \
+                                 function names",
                             )
                             .emit();
                     }
                     None => {
                         tcx.sess
-                            .struct_span_err(ident.span, "Function not found in this trait")
+                            .struct_span_err(ident.span, "function not found in this trait")
                             .emit();
                     }
                 }
@@ -1027,11 +1027,8 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef {
             for ident in &*list {
                 if let Some(dup) = set.insert(ident.name, ident.span) {
                     tcx.sess
-                        .struct_span_err(vec![dup, ident.span], "Functions names are duplicated")
-                        .note(
-                            "All `#[rustc_must_implement_one_of]` arguments \
-                            must be unique",
-                        )
+                        .struct_span_err(vec![dup, ident.span], "functions names are duplicated")
+                        .note("all `#[rustc_must_implement_one_of]` arguments must be unique")
                         .emit();
 
                     no_dups = false;
@@ -1849,6 +1846,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
                         codegen_fn_attrs.no_sanitize |= SanitizerSet::ADDRESS;
                     } else if item.has_name(sym::cfi) {
                         codegen_fn_attrs.no_sanitize |= SanitizerSet::CFI;
+                    } else if item.has_name(sym::kcfi) {
+                        codegen_fn_attrs.no_sanitize |= SanitizerSet::KCFI;
                     } else if item.has_name(sym::memory) {
                         codegen_fn_attrs.no_sanitize |= SanitizerSet::MEMORY;
                     } else if item.has_name(sym::memtag) {
@@ -1862,7 +1861,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
                     } else {
                         tcx.sess
                             .struct_span_err(item.span(), "invalid argument for `no_sanitize`")
-                            .note("expected one of: `address`, `cfi`, `hwaddress`, `memory`, `memtag`, `shadow-call-stack`, or `thread`")
+                            .note("expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`")
                             .emit();
                     }
                 }
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 639f81f20bf..cb4c35c0ce1 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -4,7 +4,6 @@ use hir::{
     GenericParamKind, HirId, Node,
 };
 use rustc_hir as hir;
-use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint;
@@ -79,7 +78,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
                     let generics = tcx.generics_of(parent_def_id.to_def_id());
                     let param_def_idx = generics.param_def_id_to_index[&param_id.to_def_id()];
                     // In the above example this would be .params[..N#0]
-                    let params = generics.params[..param_def_idx as usize].to_owned();
+                    let params = generics.params_to(param_def_idx as usize, tcx).to_owned();
                     let param_def_id_to_index =
                         params.iter().map(|param| (param.def_id, param.index)).collect();
 
@@ -143,20 +142,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
             Some(tcx.typeck_root_def_id(def_id))
         }
         Node::Item(item) => match item.kind {
-            ItemKind::OpaqueTy(hir::OpaqueTy {
-                origin:
-                    hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
-                in_trait,
-                ..
-            }) => {
-                if in_trait {
-                    assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn))
-                } else {
-                    assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn))
-                }
-                Some(fn_def_id.to_def_id())
-            }
-            ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
+            ItemKind::OpaqueTy(hir::OpaqueTy { .. }) => {
                 let parent_id = tcx.hir().get_parent_item(hir_id);
                 assert_ne!(parent_id, hir::CRATE_OWNER_ID);
                 debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index 0c9a350c295..32f86b8042c 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -1,7 +1,7 @@
 use crate::coercion::CoerceMany;
 use crate::gather_locals::GatherLocalsVisitor;
 use crate::FnCtxt;
-use crate::{GeneratorTypes, UnsafetyState};
+use crate::GeneratorTypes;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::intravisit::Visitor;
@@ -30,7 +30,6 @@ pub(super) fn check_fn<'a, 'tcx>(
     can_be_generator: Option<hir::Movability>,
 ) -> Option<GeneratorTypes<'tcx>> {
     let fn_id = fcx.tcx.hir().local_def_id_to_hir_id(fn_def_id);
-    fcx.ps.set(UnsafetyState::function(fn_sig.unsafety, fn_id));
 
     let tcx = fcx.tcx;
     let hir = tcx.hir();
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 24184bdbf5c..6763e06c0cf 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -189,7 +189,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         err: &mut Diagnostic,
         expr: &hir::Expr<'_>,
-        error: Option<TypeError<'_>>,
+        error: Option<TypeError<'tcx>>,
     ) {
         let parent = self.tcx.hir().get_parent_node(expr.hir_id);
         match (self.tcx.hir().find(parent), error) {
@@ -286,6 +286,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     err.downgrade_to_delayed_bug();
                 }
             }
+            (
+                Some(hir::Node::Expr(hir::Expr {
+                    kind: hir::ExprKind::Binary(_, lhs, rhs), ..
+                })),
+                Some(TypeError::Sorts(ExpectedFound { expected, .. })),
+            ) if rhs.hir_id == expr.hir_id
+                && self.typeck_results.borrow().expr_ty_adjusted_opt(lhs) == Some(expected) =>
+            {
+                err.span_label(lhs.span, &format!("expected because this is `{expected}`"));
+            }
             _ => {}
         }
     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 8a875e05b19..60fec05d36d 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1393,8 +1393,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         blk: &'tcx hir::Block<'tcx>,
         expected: Expectation<'tcx>,
     ) -> Ty<'tcx> {
-        let prev = self.ps.replace(self.ps.get().recurse(blk));
-
         // In some cases, blocks have just one exit, but other blocks
         // can be targeted by multiple breaks. This can happen both
         // with labeled blocks as well as when we desugar
@@ -1558,7 +1556,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         self.write_ty(blk.hir_id, ty);
 
-        self.ps.set(prev);
         ty
     }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 1e9b5752130..30b59da7852 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -8,7 +8,7 @@ use rustc_errors::ErrorGuaranteed;
 pub use suggestions::*;
 
 use crate::coercion::DynamicCoerceMany;
-use crate::{Diverges, EnclosingBreakables, Inherited, UnsafetyState};
+use crate::{Diverges, EnclosingBreakables, Inherited};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir_analysis::astconv::AstConv;
@@ -74,8 +74,6 @@ pub struct FnCtxt<'a, 'tcx> {
 
     pub(super) resume_yield_tys: Option<(Ty<'tcx>, Ty<'tcx>)>,
 
-    pub(super) ps: Cell<UnsafetyState>,
-
     /// Whether the last checked node generates a divergence (e.g.,
     /// `return` will set this to `Always`). In general, when entering
     /// an expression or other node in the tree, the initial value
@@ -129,7 +127,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ret_coercion: None,
             ret_coercion_span: Cell::new(None),
             resume_yield_tys: None,
-            ps: Cell::new(UnsafetyState::function(hir::Unsafety::Normal, hir::CRATE_HIR_ID)),
             diverges: Cell::new(Diverges::Maybe),
             enclosing_breakables: RefCell::new(EnclosingBreakables {
                 stack: Vec::new(),
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 09bd123350d..5b2352cda34 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -89,38 +89,6 @@ pub struct LocalTy<'tcx> {
     revealed_ty: Ty<'tcx>,
 }
 
-#[derive(Copy, Clone)]
-pub struct UnsafetyState {
-    pub def: hir::HirId,
-    pub unsafety: hir::Unsafety,
-    from_fn: bool,
-}
-
-impl UnsafetyState {
-    pub fn function(unsafety: hir::Unsafety, def: hir::HirId) -> UnsafetyState {
-        UnsafetyState { def, unsafety, from_fn: true }
-    }
-
-    pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState {
-        use hir::BlockCheckMode;
-        match self.unsafety {
-            // If this unsafe, then if the outer function was already marked as
-            // unsafe we shouldn't attribute the unsafe'ness to the block. This
-            // way the block can be warned about instead of ignoring this
-            // extraneous block (functions are never warned about).
-            hir::Unsafety::Unsafe if self.from_fn => self,
-
-            unsafety => {
-                let (unsafety, def) = match blk.rules {
-                    BlockCheckMode::UnsafeBlock(..) => (hir::Unsafety::Unsafe, blk.hir_id),
-                    BlockCheckMode::DefaultBlock => (unsafety, self.def),
-                };
-                UnsafetyState { def, unsafety, from_fn: false }
-            }
-        }
-    }
-}
-
 /// If this `DefId` is a "primary tables entry", returns
 /// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`.
 ///
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs
index 58d6e6d7efd..97ebed05855 100644
--- a/compiler/rustc_incremental/src/persist/fs.rs
+++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -109,6 +109,7 @@ use rustc_data_structures::{base_n, flock};
 use rustc_errors::ErrorGuaranteed;
 use rustc_fs_util::{link_or_copy, LinkOrCopy};
 use rustc_session::{Session, StableCrateId};
+use rustc_span::Symbol;
 
 use std::fs as std_fs;
 use std::io::{self, ErrorKind};
@@ -202,7 +203,7 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu
 /// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph
 pub fn prepare_session_directory(
     sess: &Session,
-    crate_name: &str,
+    crate_name: Symbol,
     stable_crate_id: StableCrateId,
 ) -> Result<(), ErrorGuaranteed> {
     if sess.opts.incremental.is_none() {
@@ -657,7 +658,7 @@ fn string_to_timestamp(s: &str) -> Result<SystemTime, ()> {
     Ok(UNIX_EPOCH + duration)
 }
 
-fn crate_path(sess: &Session, crate_name: &str, stable_crate_id: StableCrateId) -> PathBuf {
+fn crate_path(sess: &Session, crate_name: Symbol, stable_crate_id: StableCrateId) -> PathBuf {
     let incr_dir = sess.opts.incremental.as_ref().unwrap().clone();
 
     let stable_crate_id = base_n::encode(stable_crate_id.to_u64() as u128, INT_ENCODE_BASE);
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 3256ca1fb20..987559d7e47 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -56,22 +56,17 @@ use crate::infer::ExpectedFound;
 use crate::traits::error_reporting::report_object_safety_error;
 use crate::traits::{
     IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
-    StatementAsExpression,
 };
 
-use crate::errors::SuggAddLetForLetChains;
-use hir::intravisit::{walk_expr, walk_stmt};
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnosticArg};
 use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString, MultiSpan};
 use rustc_hir as hir;
-use rustc_hir::def::{CtorKind, DefKind};
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::intravisit::Visitor;
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::Node;
 use rustc_middle::dep_graph::DepContext;
-use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
 use rustc_middle::ty::{
     self, error::TypeError, List, Region, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
@@ -80,9 +75,11 @@ use rustc_middle::ty::{
 use rustc_span::{sym, symbol::kw, BytePos, DesugaringKind, Pos, Span};
 use rustc_target::spec::abi;
 use std::ops::{ControlFlow, Deref};
+use std::path::PathBuf;
 use std::{cmp, fmt, iter};
 
 mod note;
+mod suggest;
 
 pub(crate) mod need_type_info;
 pub use need_type_info::TypeAnnotationNeeded;
@@ -806,87 +803,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         }
     }
 
-    fn suggest_remove_semi_or_return_binding(
-        &self,
-        err: &mut Diagnostic,
-        first_id: Option<hir::HirId>,
-        first_ty: Ty<'tcx>,
-        first_span: Span,
-        second_id: Option<hir::HirId>,
-        second_ty: Ty<'tcx>,
-        second_span: Span,
-    ) {
-        let remove_semicolon = [
-            (first_id, self.resolve_vars_if_possible(second_ty)),
-            (second_id, self.resolve_vars_if_possible(first_ty)),
-        ]
-        .into_iter()
-        .find_map(|(id, ty)| {
-            let hir::Node::Block(blk) = self.tcx.hir().get(id?) else { return None };
-            self.could_remove_semicolon(blk, ty)
-        });
-        match remove_semicolon {
-            Some((sp, StatementAsExpression::NeedsBoxing)) => {
-                err.multipart_suggestion(
-                    "consider removing this semicolon and boxing the expressions",
-                    vec![
-                        (first_span.shrink_to_lo(), "Box::new(".to_string()),
-                        (first_span.shrink_to_hi(), ")".to_string()),
-                        (second_span.shrink_to_lo(), "Box::new(".to_string()),
-                        (second_span.shrink_to_hi(), ")".to_string()),
-                        (sp, String::new()),
-                    ],
-                    Applicability::MachineApplicable,
-                );
-            }
-            Some((sp, StatementAsExpression::CorrectType)) => {
-                err.span_suggestion_short(
-                    sp,
-                    "consider removing this semicolon",
-                    "",
-                    Applicability::MachineApplicable,
-                );
-            }
-            None => {
-                for (id, ty) in [(first_id, second_ty), (second_id, first_ty)] {
-                    if let Some(id) = id
-                        && let hir::Node::Block(blk) = self.tcx.hir().get(id)
-                        && self.consider_returning_binding(blk, ty, err)
-                    {
-                        break;
-                    }
-                }
-            }
-        }
-    }
-
-    fn suggest_boxing_for_return_impl_trait(
-        &self,
-        err: &mut Diagnostic,
-        return_sp: Span,
-        arm_spans: impl Iterator<Item = Span>,
-    ) {
-        err.multipart_suggestion(
-            "you could change the return type to be a boxed trait object",
-            vec![
-                (return_sp.with_hi(return_sp.lo() + BytePos(4)), "Box<dyn".to_string()),
-                (return_sp.shrink_to_hi(), ">".to_string()),
-            ],
-            Applicability::MaybeIncorrect,
-        );
-        let sugg = arm_spans
-            .flat_map(|sp| {
-                [(sp.shrink_to_lo(), "Box::new(".to_string()), (sp.shrink_to_hi(), ")".to_string())]
-                    .into_iter()
-            })
-            .collect::<Vec<_>>();
-        err.multipart_suggestion(
-            "if you change the return type to expect trait objects, box the returned expressions",
-            sugg,
-            Applicability::MaybeIncorrect,
-        );
-    }
-
     /// Given that `other_ty` is the same as a type argument for `name` in `sub`, populate `value`
     /// highlighting `name` and every type argument that isn't at `pos` (which is `other_ty`), and
     /// populate `other_value` with `other_ty`.
@@ -1352,10 +1268,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             .map(|(mod_str, _)| mod_str.len() + separator_len)
                             .sum();
 
-                    debug!(
-                        "cmp: separator_len={}, split_idx={}, min_len={}",
-                        separator_len, split_idx, min_len
-                    );
+                    debug!(?separator_len, ?split_idx, ?min_len, "cmp");
 
                     if split_idx >= min_len {
                         // paths are identical, highlight everything
@@ -1366,7 +1279,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     } else {
                         let (common, uniq1) = t1_str.split_at(split_idx);
                         let (_, uniq2) = t2_str.split_at(split_idx);
-                        debug!("cmp: common={}, uniq1={}, uniq2={}", common, uniq1, uniq2);
+                        debug!(?common, ?uniq1, ?uniq2, "cmp");
 
                         values.0.push_normal(common);
                         values.0.push_highlighted(uniq1);
@@ -1659,17 +1572,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     }
                     ValuePairs::Regions(_) => (false, Mismatch::Fixed("lifetime")),
                 };
-                let vals = match self.values_str(values) {
-                    Some((expected, found)) => Some((expected, found)),
-                    None => {
-                        // Derived error. Cancel the emitter.
-                        // NOTE(eddyb) this was `.cancel()`, but `diag`
-                        // is borrowed, so we can't fully defuse it.
-                        diag.downgrade_to_delayed_bug();
-                        return;
-                    }
+                let Some(vals) = self.values_str(values) else {
+                    // Derived error. Cancel the emitter.
+                    // NOTE(eddyb) this was `.cancel()`, but `diag`
+                    // is borrowed, so we can't fully defuse it.
+                    diag.downgrade_to_delayed_bug();
+                    return;
                 };
-                (vals, exp_found, is_simple_error, Some(values))
+                (Some(vals), exp_found, is_simple_error, Some(values))
             }
         };
 
@@ -1701,7 +1611,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             label_or_note(span, &terr.to_string());
         }
 
-        if let Some((expected, found)) = expected_found {
+        if let Some((expected, found, exp_p, found_p)) = expected_found {
             let (expected_label, found_label, exp_found) = match exp_found {
                 Mismatch::Variable(ef) => (
                     ef.expected.prefix_string(self.tcx),
@@ -1818,32 +1728,41 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 }
                 TypeError::Sorts(values) => {
                     let extra = expected == found;
-                    let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) {
-                        (true, ty::Opaque(def_id, _)) => {
-                            let sm = self.tcx.sess.source_map();
-                            let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
-                            format!(
-                                " (opaque type at <{}:{}:{}>)",
-                                sm.filename_for_diagnostics(&pos.file.name),
-                                pos.line,
-                                pos.col.to_usize() + 1,
-                            )
-                        }
-                        (true, ty::Projection(proj))
-                            if self.tcx.def_kind(proj.item_def_id)
-                                == DefKind::ImplTraitPlaceholder =>
-                        {
-                            let sm = self.tcx.sess.source_map();
-                            let pos = sm.lookup_char_pos(self.tcx.def_span(proj.item_def_id).lo());
-                            format!(
-                                " (trait associated opaque type at <{}:{}:{}>)",
-                                sm.filename_for_diagnostics(&pos.file.name),
-                                pos.line,
-                                pos.col.to_usize() + 1,
-                            )
+                    let sort_string = |ty: Ty<'tcx>, path: Option<PathBuf>| {
+                        let mut s = match (extra, ty.kind()) {
+                            (true, ty::Opaque(def_id, _)) => {
+                                let sm = self.tcx.sess.source_map();
+                                let pos = sm.lookup_char_pos(self.tcx.def_span(*def_id).lo());
+                                format!(
+                                    " (opaque type at <{}:{}:{}>)",
+                                    sm.filename_for_diagnostics(&pos.file.name),
+                                    pos.line,
+                                    pos.col.to_usize() + 1,
+                                )
+                            }
+                            (true, ty::Projection(proj))
+                                if self.tcx.def_kind(proj.item_def_id)
+                                    == DefKind::ImplTraitPlaceholder =>
+                            {
+                                let sm = self.tcx.sess.source_map();
+                                let pos = sm.lookup_char_pos(self.tcx.def_span(proj.item_def_id).lo());
+                                format!(
+                                    " (trait associated opaque type at <{}:{}:{}>)",
+                                    sm.filename_for_diagnostics(&pos.file.name),
+                                    pos.line,
+                                    pos.col.to_usize() + 1,
+                                )
+                            }
+                            (true, _) => format!(" ({})", ty.sort_string(self.tcx)),
+                            (false, _) => "".to_string(),
+                        };
+                        if let Some(path) = path {
+                            s.push_str(&format!(
+                                "\nthe full type name has been written to '{}'",
+                                path.display(),
+                            ));
                         }
-                        (true, _) => format!(" ({})", ty.sort_string(self.tcx)),
-                        (false, _) => "".to_string(),
+                        s
                     };
                     if !(values.expected.is_simple_text() && values.found.is_simple_text())
                         || (exp_found.map_or(false, |ef| {
@@ -1865,8 +1784,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                             expected,
                             &found_label,
                             found,
-                            &sort_string(values.expected),
-                            &sort_string(values.found),
+                            &sort_string(values.expected, exp_p),
+                            &sort_string(values.found, found_p),
                         );
                     }
                 }
@@ -1940,310 +1859,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         debug!(?diag);
     }
 
-    fn suggest_tuple_pattern(
-        &self,
-        cause: &ObligationCause<'tcx>,
-        exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
-        diag: &mut Diagnostic,
-    ) {
-        // Heavily inspired by `FnCtxt::suggest_compatible_variants`, with
-        // some modifications due to that being in typeck and this being in infer.
-        if let ObligationCauseCode::Pattern { .. } = cause.code() {
-            if let ty::Adt(expected_adt, substs) = exp_found.expected.kind() {
-                let compatible_variants: Vec<_> = expected_adt
-                    .variants()
-                    .iter()
-                    .filter(|variant| {
-                        variant.fields.len() == 1 && variant.ctor_kind() == Some(CtorKind::Fn)
-                    })
-                    .filter_map(|variant| {
-                        let sole_field = &variant.fields[0];
-                        let sole_field_ty = sole_field.ty(self.tcx, substs);
-                        if self.same_type_modulo_infer(sole_field_ty, exp_found.found) {
-                            let variant_path =
-                                with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id));
-                            // FIXME #56861: DRYer prelude filtering
-                            if let Some(path) = variant_path.strip_prefix("std::prelude::") {
-                                if let Some((_, path)) = path.split_once("::") {
-                                    return Some(path.to_string());
-                                }
-                            }
-                            Some(variant_path)
-                        } else {
-                            None
-                        }
-                    })
-                    .collect();
-                match &compatible_variants[..] {
-                    [] => {}
-                    [variant] => {
-                        diag.multipart_suggestion_verbose(
-                            &format!("try wrapping the pattern in `{}`", variant),
-                            vec![
-                                (cause.span.shrink_to_lo(), format!("{}(", variant)),
-                                (cause.span.shrink_to_hi(), ")".to_string()),
-                            ],
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                    _ => {
-                        // More than one matching variant.
-                        diag.multipart_suggestions(
-                            &format!(
-                                "try wrapping the pattern in a variant of `{}`",
-                                self.tcx.def_path_str(expected_adt.did())
-                            ),
-                            compatible_variants.into_iter().map(|variant| {
-                                vec![
-                                    (cause.span.shrink_to_lo(), format!("{}(", variant)),
-                                    (cause.span.shrink_to_hi(), ")".to_string()),
-                                ]
-                            }),
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                }
-            }
-        }
-    }
-
-    /// A possible error is to forget to add `.await` when using futures:
-    ///
-    /// ```compile_fail,E0308
-    /// async fn make_u32() -> u32 {
-    ///     22
-    /// }
-    ///
-    /// fn take_u32(x: u32) {}
-    ///
-    /// async fn foo() {
-    ///     let x = make_u32();
-    ///     take_u32(x);
-    /// }
-    /// ```
-    ///
-    /// This routine checks if the found type `T` implements `Future<Output=U>` where `U` is the
-    /// expected type. If this is the case, and we are inside of an async body, it suggests adding
-    /// `.await` to the tail of the expression.
-    fn suggest_await_on_expect_found(
-        &self,
-        cause: &ObligationCause<'tcx>,
-        exp_span: Span,
-        exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
-        diag: &mut Diagnostic,
-    ) {
-        debug!(
-            "suggest_await_on_expect_found: exp_span={:?}, expected_ty={:?}, found_ty={:?}",
-            exp_span, exp_found.expected, exp_found.found,
-        );
-
-        if let ObligationCauseCode::CompareImplItemObligation { .. } = cause.code() {
-            return;
-        }
-
-        match (
-            self.get_impl_future_output_ty(exp_found.expected),
-            self.get_impl_future_output_ty(exp_found.found),
-        ) {
-            (Some(exp), Some(found)) if self.same_type_modulo_infer(exp, found) => match cause
-                .code()
-            {
-                ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
-                    let then_span = self.find_block_span_from_hir_id(*then_id);
-                    diag.multipart_suggestion(
-                        "consider `await`ing on both `Future`s",
-                        vec![
-                            (then_span.shrink_to_hi(), ".await".to_string()),
-                            (exp_span.shrink_to_hi(), ".await".to_string()),
-                        ],
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-                ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
-                    prior_arms,
-                    ..
-                }) => {
-                    if let [.., arm_span] = &prior_arms[..] {
-                        diag.multipart_suggestion(
-                            "consider `await`ing on both `Future`s",
-                            vec![
-                                (arm_span.shrink_to_hi(), ".await".to_string()),
-                                (exp_span.shrink_to_hi(), ".await".to_string()),
-                            ],
-                            Applicability::MaybeIncorrect,
-                        );
-                    } else {
-                        diag.help("consider `await`ing on both `Future`s");
-                    }
-                }
-                _ => {
-                    diag.help("consider `await`ing on both `Future`s");
-                }
-            },
-            (_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => {
-                diag.span_suggestion_verbose(
-                    exp_span.shrink_to_hi(),
-                    "consider `await`ing on the `Future`",
-                    ".await",
-                    Applicability::MaybeIncorrect,
-                );
-            }
-            (Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
-            {
-                ObligationCauseCode::Pattern { span: Some(then_span), .. } => {
-                    diag.span_suggestion_verbose(
-                        then_span.shrink_to_hi(),
-                        "consider `await`ing on the `Future`",
-                        ".await",
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-                ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
-                    let then_span = self.find_block_span_from_hir_id(*then_id);
-                    diag.span_suggestion_verbose(
-                        then_span.shrink_to_hi(),
-                        "consider `await`ing on the `Future`",
-                        ".await",
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-                ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
-                    ref prior_arms,
-                    ..
-                }) => {
-                    diag.multipart_suggestion_verbose(
-                        "consider `await`ing on the `Future`",
-                        prior_arms
-                            .iter()
-                            .map(|arm| (arm.shrink_to_hi(), ".await".to_string()))
-                            .collect(),
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-                _ => {}
-            },
-            _ => {}
-        }
-    }
-
-    fn suggest_accessing_field_where_appropriate(
-        &self,
-        cause: &ObligationCause<'tcx>,
-        exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
-        diag: &mut Diagnostic,
-    ) {
-        debug!(
-            "suggest_accessing_field_where_appropriate(cause={:?}, exp_found={:?})",
-            cause, exp_found
-        );
-        if let ty::Adt(expected_def, expected_substs) = exp_found.expected.kind() {
-            if expected_def.is_enum() {
-                return;
-            }
-
-            if let Some((name, ty)) = expected_def
-                .non_enum_variant()
-                .fields
-                .iter()
-                .filter(|field| field.vis.is_accessible_from(field.did, self.tcx))
-                .map(|field| (field.name, field.ty(self.tcx, expected_substs)))
-                .find(|(_, ty)| self.same_type_modulo_infer(*ty, exp_found.found))
-            {
-                if let ObligationCauseCode::Pattern { span: Some(span), .. } = *cause.code() {
-                    if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-                        let suggestion = if expected_def.is_struct() {
-                            format!("{}.{}", snippet, name)
-                        } else if expected_def.is_union() {
-                            format!("unsafe {{ {}.{} }}", snippet, name)
-                        } else {
-                            return;
-                        };
-                        diag.span_suggestion(
-                            span,
-                            &format!(
-                                "you might have meant to use field `{}` whose type is `{}`",
-                                name, ty
-                            ),
-                            suggestion,
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
-                }
-            }
-        }
-    }
-
-    /// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
-    /// suggests it.
-    fn suggest_as_ref_where_appropriate(
-        &self,
-        span: Span,
-        exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
-        diag: &mut Diagnostic,
-    ) {
-        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
-            && let Some(msg) = self.should_suggest_as_ref(exp_found.expected, exp_found.found)
-        {
-            diag.span_suggestion(
-                span,
-                msg,
-                // HACK: fix issue# 100605, suggesting convert from &Option<T> to Option<&T>, remove the extra `&`
-                format!("{}.as_ref()", snippet.trim_start_matches('&')),
-                Applicability::MachineApplicable,
-            );
-        }
-    }
-
-    pub fn should_suggest_as_ref(&self, expected: Ty<'tcx>, found: Ty<'tcx>) -> Option<&str> {
-        if let (ty::Adt(exp_def, exp_substs), ty::Ref(_, found_ty, _)) =
-            (expected.kind(), found.kind())
-        {
-            if let ty::Adt(found_def, found_substs) = *found_ty.kind() {
-                if exp_def == &found_def {
-                    let have_as_ref = &[
-                        (
-                            sym::Option,
-                            "you can convert from `&Option<T>` to `Option<&T>` using \
-                        `.as_ref()`",
-                        ),
-                        (
-                            sym::Result,
-                            "you can convert from `&Result<T, E>` to \
-                        `Result<&T, &E>` using `.as_ref()`",
-                        ),
-                    ];
-                    if let Some(msg) = have_as_ref.iter().find_map(|(name, msg)| {
-                        self.tcx.is_diagnostic_item(*name, exp_def.did()).then_some(msg)
-                    }) {
-                        let mut show_suggestion = true;
-                        for (exp_ty, found_ty) in
-                            iter::zip(exp_substs.types(), found_substs.types())
-                        {
-                            match *exp_ty.kind() {
-                                ty::Ref(_, exp_ty, _) => {
-                                    match (exp_ty.kind(), found_ty.kind()) {
-                                        (_, ty::Param(_))
-                                        | (_, ty::Infer(_))
-                                        | (ty::Param(_), _)
-                                        | (ty::Infer(_), _) => {}
-                                        _ if self.same_type_modulo_infer(exp_ty, found_ty) => {}
-                                        _ => show_suggestion = false,
-                                    };
-                                }
-                                ty::Param(_) | ty::Infer(_) => {}
-                                _ => show_suggestion = false,
-                            }
-                        }
-                        if show_suggestion {
-                            return Some(*msg);
-                        }
-                    }
-                }
-            }
-        }
-        None
-    }
-
     pub fn report_and_explain_type_error(
         &self,
         trace: TypeTrace<'tcx>,
@@ -2339,7 +1954,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 let code = trace.cause.code();
                 if let &MatchExpressionArm(box MatchExpressionArmCause { source, .. }) = code
                     && let hir::MatchSource::TryDesugar = source
-                    && let Some((expected_ty, found_ty)) = self.values_str(trace.values)
+                    && let Some((expected_ty, found_ty, _, _)) = self.values_str(trace.values)
                 {
                     err.note(&format!(
                         "`?` operator cannot convert from `{}` to `{}`",
@@ -2357,67 +1972,6 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         diag
     }
 
-    /// Try to find code with pattern `if Some(..) = expr`
-    /// use a `visitor` to mark the `if` which its span contains given error span,
-    /// and then try to find a assignment in the `cond` part, which span is equal with error span
-    fn suggest_let_for_letchains(
-        &self,
-        err: &mut Diagnostic,
-        cause: &ObligationCause<'_>,
-        span: Span,
-    ) {
-        let hir = self.tcx.hir();
-        let fn_hir_id = hir.get_parent_node(cause.body_id);
-        if let Some(node) = self.tcx.hir().find(fn_hir_id) &&
-            let hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Fn(_sig, _, body_id), ..
-                }) = node {
-        let body = hir.body(*body_id);
-
-        /// Find the if expression with given span
-        struct IfVisitor {
-            pub result: bool,
-            pub found_if: bool,
-            pub err_span: Span,
-        }
-
-        impl<'v> Visitor<'v> for IfVisitor {
-            fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
-                if self.result { return; }
-                match ex.kind {
-                    hir::ExprKind::If(cond, _, _) => {
-                        self.found_if = true;
-                        walk_expr(self, cond);
-                        self.found_if = false;
-                    }
-                    _ => walk_expr(self, ex),
-                }
-            }
-
-            fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
-                if let hir::StmtKind::Local(hir::Local {
-                        span, pat: hir::Pat{..}, ty: None, init: Some(_), ..
-                    }) = &ex.kind
-                    && self.found_if
-                    && span.eq(&self.err_span) {
-                        self.result = true;
-                }
-                walk_stmt(self, ex);
-            }
-
-            fn visit_body(&mut self, body: &'v hir::Body<'v>) {
-                hir::intravisit::walk_body(self, body);
-            }
-        }
-
-        let mut visitor = IfVisitor { err_span: span, found_if: false, result: false };
-        visitor.visit_body(&body);
-        if visitor.result {
-                err.subdiagnostic(SuggAddLetForLetChains{span: span.shrink_to_lo()});
-            }
-        }
-    }
-
     fn emit_tuple_wrap_err(
         &self,
         err: &mut Diagnostic,
@@ -2455,7 +2009,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
     fn values_str(
         &self,
         values: ValuePairs<'tcx>,
-    ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
+    ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
+    {
         match values {
             infer::Regions(exp_found) => self.expected_found_str(exp_found),
             infer::Terms(exp_found) => self.expected_found_str_term(exp_found),
@@ -2465,7 +2020,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     found: exp_found.found.print_only_trait_path(),
                 };
                 match self.expected_found_str(pretty_exp_found) {
-                    Some((expected, found)) if expected == found => {
+                    Some((expected, found, _, _)) if expected == found => {
                         self.expected_found_str(exp_found)
                     }
                     ret => ret,
@@ -2477,7 +2032,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     found: exp_found.found.print_only_trait_path(),
                 };
                 match self.expected_found_str(pretty_exp_found) {
-                    Some((expected, found)) if expected == found => {
+                    Some((expected, found, _, _)) if expected == found => {
                         self.expected_found_str(exp_found)
                     }
                     ret => ret,
@@ -2489,17 +2044,41 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
     fn expected_found_str_term(
         &self,
         exp_found: ty::error::ExpectedFound<ty::Term<'tcx>>,
-    ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
+    ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
+    {
         let exp_found = self.resolve_vars_if_possible(exp_found);
         if exp_found.references_error() {
             return None;
         }
 
         Some(match (exp_found.expected.unpack(), exp_found.found.unpack()) {
-            (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => self.cmp(expected, found),
+            (ty::TermKind::Ty(expected), ty::TermKind::Ty(found)) => {
+                let (mut exp, mut fnd) = self.cmp(expected, found);
+                // Use the terminal width as the basis to determine when to compress the printed
+                // out type, but give ourselves some leeway to avoid ending up creating a file for
+                // a type that is somewhat shorter than the path we'd write to.
+                let len = self.tcx.sess().diagnostic_width() + 40;
+                let exp_s = exp.content();
+                let fnd_s = fnd.content();
+                let mut exp_p = None;
+                let mut fnd_p = None;
+                if exp_s.len() > len {
+                    let (exp_s, exp_path) = self.tcx.short_ty_string(expected);
+                    exp = DiagnosticStyledString::highlighted(exp_s);
+                    exp_p = exp_path;
+                }
+                if fnd_s.len() > len {
+                    let (fnd_s, fnd_path) = self.tcx.short_ty_string(found);
+                    fnd = DiagnosticStyledString::highlighted(fnd_s);
+                    fnd_p = fnd_path;
+                }
+                (exp, fnd, exp_p, fnd_p)
+            }
             _ => (
                 DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
                 DiagnosticStyledString::highlighted(exp_found.found.to_string()),
+                None,
+                None,
             ),
         })
     }
@@ -2508,7 +2087,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
     fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
         &self,
         exp_found: ty::error::ExpectedFound<T>,
-    ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> {
+    ) -> Option<(DiagnosticStyledString, DiagnosticStyledString, Option<PathBuf>, Option<PathBuf>)>
+    {
         let exp_found = self.resolve_vars_if_possible(exp_found);
         if exp_found.references_error() {
             return None;
@@ -2517,6 +2097,8 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         Some((
             DiagnosticStyledString::highlighted(exp_found.expected.to_string()),
             DiagnosticStyledString::highlighted(exp_found.found.to_string()),
+            None,
+            None,
         ))
     }
 
@@ -2850,36 +2432,29 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         debug!("report_sub_sup_conflict: sup_region={:?}", sup_region);
         debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin);
 
-        if let (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) =
-            (&sup_origin, &sub_origin)
+        if let infer::Subtype(ref sup_trace) = sup_origin
+            && let infer::Subtype(ref sub_trace) = sub_origin
+            && let Some((sup_expected, sup_found, _, _)) = self.values_str(sup_trace.values)
+            && let Some((sub_expected, sub_found, _, _)) = self.values_str(sub_trace.values)
+            && sub_expected == sup_expected
+            && sub_found == sup_found
         {
-            debug!("report_sub_sup_conflict: sup_trace={:?}", sup_trace);
-            debug!("report_sub_sup_conflict: sub_trace={:?}", sub_trace);
-            debug!("report_sub_sup_conflict: sup_trace.values={:?}", sup_trace.values);
-            debug!("report_sub_sup_conflict: sub_trace.values={:?}", sub_trace.values);
-
-            if let (Some((sup_expected, sup_found)), Some((sub_expected, sub_found))) =
-                (self.values_str(sup_trace.values), self.values_str(sub_trace.values))
-            {
-                if sub_expected == sup_expected && sub_found == sup_found {
-                    note_and_explain_region(
-                        self.tcx,
-                        &mut err,
-                        "...but the lifetime must also be valid for ",
-                        sub_region,
-                        "...",
-                        None,
-                    );
-                    err.span_note(
-                        sup_trace.cause.span,
-                        &format!("...so that the {}", sup_trace.cause.as_requirement_str()),
-                    );
+            note_and_explain_region(
+                self.tcx,
+                &mut err,
+                "...but the lifetime must also be valid for ",
+                sub_region,
+                "...",
+                None,
+            );
+            err.span_note(
+                sup_trace.cause.span,
+                &format!("...so that the {}", sup_trace.cause.as_requirement_str()),
+            );
 
-                    err.note_expected_found(&"", sup_expected, &"", sup_found);
-                    err.emit();
-                    return;
-                }
-            }
+            err.note_expected_found(&"", sup_expected, &"", sup_found);
+            err.emit();
+            return;
         }
 
         self.note_region_origin(&mut err, &sup_origin);
@@ -3228,211 +2803,3 @@ impl<'tcx> InferCtxt<'tcx> {
         }
     }
 }
-
-impl<'tcx> TypeErrCtxt<'_, 'tcx> {
-    /// Be helpful when the user wrote `{... expr; }` and taking the `;` off
-    /// is enough to fix the error.
-    pub fn could_remove_semicolon(
-        &self,
-        blk: &'tcx hir::Block<'tcx>,
-        expected_ty: Ty<'tcx>,
-    ) -> Option<(Span, StatementAsExpression)> {
-        let blk = blk.innermost_block();
-        // Do not suggest if we have a tail expr.
-        if blk.expr.is_some() {
-            return None;
-        }
-        let last_stmt = blk.stmts.last()?;
-        let hir::StmtKind::Semi(ref last_expr) = last_stmt.kind else {
-            return None;
-        };
-        let last_expr_ty = self.typeck_results.as_ref()?.expr_ty_opt(*last_expr)?;
-        let needs_box = match (last_expr_ty.kind(), expected_ty.kind()) {
-            _ if last_expr_ty.references_error() => return None,
-            _ if self.same_type_modulo_infer(last_expr_ty, expected_ty) => {
-                StatementAsExpression::CorrectType
-            }
-            (ty::Opaque(last_def_id, _), ty::Opaque(exp_def_id, _))
-                if last_def_id == exp_def_id =>
-            {
-                StatementAsExpression::CorrectType
-            }
-            (ty::Opaque(last_def_id, last_bounds), ty::Opaque(exp_def_id, exp_bounds)) => {
-                debug!(
-                    "both opaque, likely future {:?} {:?} {:?} {:?}",
-                    last_def_id, last_bounds, exp_def_id, exp_bounds
-                );
-
-                let last_local_id = last_def_id.as_local()?;
-                let exp_local_id = exp_def_id.as_local()?;
-
-                match (
-                    &self.tcx.hir().expect_item(last_local_id).kind,
-                    &self.tcx.hir().expect_item(exp_local_id).kind,
-                ) {
-                    (
-                        hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: last_bounds, .. }),
-                        hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: exp_bounds, .. }),
-                    ) if iter::zip(*last_bounds, *exp_bounds).all(|(left, right)| {
-                        match (left, right) {
-                            (
-                                hir::GenericBound::Trait(tl, ml),
-                                hir::GenericBound::Trait(tr, mr),
-                            ) if tl.trait_ref.trait_def_id() == tr.trait_ref.trait_def_id()
-                                && ml == mr =>
-                            {
-                                true
-                            }
-                            (
-                                hir::GenericBound::LangItemTrait(langl, _, _, argsl),
-                                hir::GenericBound::LangItemTrait(langr, _, _, argsr),
-                            ) if langl == langr => {
-                                // FIXME: consider the bounds!
-                                debug!("{:?} {:?}", argsl, argsr);
-                                true
-                            }
-                            _ => false,
-                        }
-                    }) =>
-                    {
-                        StatementAsExpression::NeedsBoxing
-                    }
-                    _ => StatementAsExpression::CorrectType,
-                }
-            }
-            _ => return None,
-        };
-        let span = if last_stmt.span.from_expansion() {
-            let mac_call = rustc_span::source_map::original_sp(last_stmt.span, blk.span);
-            self.tcx.sess.source_map().mac_call_stmt_semi_span(mac_call)?
-        } else {
-            last_stmt.span.with_lo(last_stmt.span.hi() - BytePos(1))
-        };
-        Some((span, needs_box))
-    }
-
-    /// Suggest returning a local binding with a compatible type if the block
-    /// has no return expression.
-    pub fn consider_returning_binding(
-        &self,
-        blk: &'tcx hir::Block<'tcx>,
-        expected_ty: Ty<'tcx>,
-        err: &mut Diagnostic,
-    ) -> bool {
-        let blk = blk.innermost_block();
-        // Do not suggest if we have a tail expr.
-        if blk.expr.is_some() {
-            return false;
-        }
-        let mut shadowed = FxIndexSet::default();
-        let mut candidate_idents = vec![];
-        let mut find_compatible_candidates = |pat: &hir::Pat<'_>| {
-            if let hir::PatKind::Binding(_, hir_id, ident, _) = &pat.kind
-                && let Some(pat_ty) = self
-                    .typeck_results
-                    .as_ref()
-                    .and_then(|typeck_results| typeck_results.node_type_opt(*hir_id))
-            {
-                let pat_ty = self.resolve_vars_if_possible(pat_ty);
-                if self.same_type_modulo_infer(pat_ty, expected_ty)
-                    && !(pat_ty, expected_ty).references_error()
-                    && shadowed.insert(ident.name)
-                {
-                    candidate_idents.push((*ident, pat_ty));
-                }
-            }
-            true
-        };
-
-        let hir = self.tcx.hir();
-        for stmt in blk.stmts.iter().rev() {
-            let hir::StmtKind::Local(local) = &stmt.kind else { continue; };
-            local.pat.walk(&mut find_compatible_candidates);
-        }
-        match hir.find(hir.get_parent_node(blk.hir_id)) {
-            Some(hir::Node::Expr(hir::Expr { hir_id, .. })) => {
-                match hir.find(hir.get_parent_node(*hir_id)) {
-                    Some(hir::Node::Arm(hir::Arm { pat, .. })) => {
-                        pat.walk(&mut find_compatible_candidates);
-                    }
-                    Some(
-                        hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body), .. })
-                        | hir::Node::ImplItem(hir::ImplItem {
-                            kind: hir::ImplItemKind::Fn(_, body),
-                            ..
-                        })
-                        | hir::Node::TraitItem(hir::TraitItem {
-                            kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body)),
-                            ..
-                        })
-                        | hir::Node::Expr(hir::Expr {
-                            kind: hir::ExprKind::Closure(hir::Closure { body, .. }),
-                            ..
-                        }),
-                    ) => {
-                        for param in hir.body(*body).params {
-                            param.pat.walk(&mut find_compatible_candidates);
-                        }
-                    }
-                    Some(hir::Node::Expr(hir::Expr {
-                        kind:
-                            hir::ExprKind::If(
-                                hir::Expr { kind: hir::ExprKind::Let(let_), .. },
-                                then_block,
-                                _,
-                            ),
-                        ..
-                    })) if then_block.hir_id == *hir_id => {
-                        let_.pat.walk(&mut find_compatible_candidates);
-                    }
-                    _ => {}
-                }
-            }
-            _ => {}
-        }
-
-        match &candidate_idents[..] {
-            [(ident, _ty)] => {
-                let sm = self.tcx.sess.source_map();
-                if let Some(stmt) = blk.stmts.last() {
-                    let stmt_span = sm.stmt_span(stmt.span, blk.span);
-                    let sugg = if sm.is_multiline(blk.span)
-                        && let Some(spacing) = sm.indentation_before(stmt_span)
-                    {
-                        format!("\n{spacing}{ident}")
-                    } else {
-                        format!(" {ident}")
-                    };
-                    err.span_suggestion_verbose(
-                        stmt_span.shrink_to_hi(),
-                        format!("consider returning the local binding `{ident}`"),
-                        sugg,
-                        Applicability::MaybeIncorrect,
-                    );
-                } else {
-                    let sugg = if sm.is_multiline(blk.span)
-                        && let Some(spacing) = sm.indentation_before(blk.span.shrink_to_lo())
-                    {
-                        format!("\n{spacing}    {ident}\n{spacing}")
-                    } else {
-                        format!(" {ident} ")
-                    };
-                    let left_span = sm.span_through_char(blk.span, '{').shrink_to_hi();
-                    err.span_suggestion_verbose(
-                        sm.span_extend_while(left_span, |c| c.is_whitespace()).unwrap_or(left_span),
-                        format!("consider returning the local binding `{ident}`"),
-                        sugg,
-                        Applicability::MaybeIncorrect,
-                    );
-                }
-                true
-            }
-            values if (1..3).contains(&values.len()) => {
-                let spans = values.iter().map(|(ident, _)| ident.span).collect::<Vec<_>>();
-                err.span_note(spans, "consider returning one of these bindings");
-                true
-            }
-            _ => false,
-        }
-    }
-}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index 41b115f3377..d2dffa4a0b7 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -16,7 +16,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
                 span: trace.cause.span,
                 requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
-                expected_found: self.values_str(trace.values),
+                expected_found: self.values_str(trace.values).map(|(e, f, _, _)| (e, f)),
             }
             .add_to_diagnostic(err),
             infer::Reborrow(span) => {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_region.rs b/compiler/rustc_infer/src/infer/error_reporting/note_region.rs
new file mode 100644
index 00000000000..41b115f3377
--- /dev/null
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_region.rs
@@ -0,0 +1,427 @@
+use crate::errors::RegionOriginNote;
+use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt};
+use crate::infer::{self, SubregionOrigin};
+use rustc_errors::{
+    fluent, struct_span_err, AddToDiagnostic, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
+};
+use rustc_middle::traits::ObligationCauseCode;
+use rustc_middle::ty::error::TypeError;
+use rustc_middle::ty::{self, Region};
+
+use super::ObligationCauseAsDiagArg;
+
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
+    pub(super) fn note_region_origin(&self, err: &mut Diagnostic, origin: &SubregionOrigin<'tcx>) {
+        match *origin {
+            infer::Subtype(ref trace) => RegionOriginNote::WithRequirement {
+                span: trace.cause.span,
+                requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
+                expected_found: self.values_str(trace.values),
+            }
+            .add_to_diagnostic(err),
+            infer::Reborrow(span) => {
+                RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diagnostic(err)
+            }
+            infer::ReborrowUpvar(span, ref upvar_id) => {
+                let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
+                RegionOriginNote::WithName {
+                    span,
+                    msg: fluent::infer_reborrow,
+                    name: &var_name.to_string(),
+                    continues: false,
+                }
+                .add_to_diagnostic(err);
+            }
+            infer::RelateObjectBound(span) => {
+                RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound }
+                    .add_to_diagnostic(err);
+            }
+            infer::DataBorrowed(ty, span) => {
+                RegionOriginNote::WithName {
+                    span,
+                    msg: fluent::infer_data_borrowed,
+                    name: &self.ty_to_string(ty),
+                    continues: false,
+                }
+                .add_to_diagnostic(err);
+            }
+            infer::ReferenceOutlivesReferent(ty, span) => {
+                RegionOriginNote::WithName {
+                    span,
+                    msg: fluent::infer_reference_outlives_referent,
+                    name: &self.ty_to_string(ty),
+                    continues: false,
+                }
+                .add_to_diagnostic(err);
+            }
+            infer::RelateParamBound(span, ty, opt_span) => {
+                RegionOriginNote::WithName {
+                    span,
+                    msg: fluent::infer_relate_param_bound,
+                    name: &self.ty_to_string(ty),
+                    continues: opt_span.is_some(),
+                }
+                .add_to_diagnostic(err);
+                if let Some(span) = opt_span {
+                    RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 }
+                        .add_to_diagnostic(err);
+                }
+            }
+            infer::RelateRegionParamBound(span) => {
+                RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound }
+                    .add_to_diagnostic(err);
+            }
+            infer::CompareImplItemObligation { span, .. } => {
+                RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation }
+                    .add_to_diagnostic(err);
+            }
+            infer::CheckAssociatedTypeBounds { ref parent, .. } => {
+                self.note_region_origin(err, &parent);
+            }
+            infer::AscribeUserTypeProvePredicate(span) => {
+                RegionOriginNote::Plain {
+                    span,
+                    msg: fluent::infer_ascribe_user_type_prove_predicate,
+                }
+                .add_to_diagnostic(err);
+            }
+        }
+    }
+
+    pub(super) fn report_concrete_failure(
+        &self,
+        origin: SubregionOrigin<'tcx>,
+        sub: Region<'tcx>,
+        sup: Region<'tcx>,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+        match origin {
+            infer::Subtype(box trace) => {
+                let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
+                let mut err = self.report_and_explain_type_error(trace, terr);
+                match (*sub, *sup) {
+                    (ty::RePlaceholder(_), ty::RePlaceholder(_)) => {}
+                    (ty::RePlaceholder(_), _) => {
+                        note_and_explain_region(
+                            self.tcx,
+                            &mut err,
+                            "",
+                            sup,
+                            " doesn't meet the lifetime requirements",
+                            None,
+                        );
+                    }
+                    (_, ty::RePlaceholder(_)) => {
+                        note_and_explain_region(
+                            self.tcx,
+                            &mut err,
+                            "the required lifetime does not necessarily outlive ",
+                            sub,
+                            "",
+                            None,
+                        );
+                    }
+                    _ => {
+                        note_and_explain_region(self.tcx, &mut err, "", sup, "...", None);
+                        note_and_explain_region(
+                            self.tcx,
+                            &mut err,
+                            "...does not necessarily outlive ",
+                            sub,
+                            "",
+                            None,
+                        );
+                    }
+                }
+                err
+            }
+            infer::Reborrow(span) => {
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0312,
+                    "lifetime of reference outlives lifetime of borrowed content..."
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "...the reference is valid for ",
+                    sub,
+                    "...",
+                    None,
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "...but the borrowed content is only valid for ",
+                    sup,
+                    "",
+                    None,
+                );
+                err
+            }
+            infer::ReborrowUpvar(span, ref upvar_id) => {
+                let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0313,
+                    "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...",
+                    var_name
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "...the borrowed pointer is valid for ",
+                    sub,
+                    "...",
+                    None,
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    &format!("...but `{}` is only valid for ", var_name),
+                    sup,
+                    "",
+                    None,
+                );
+                err
+            }
+            infer::RelateObjectBound(span) => {
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0476,
+                    "lifetime of the source pointer does not outlive lifetime bound of the \
+                     object type"
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "object type is valid for ",
+                    sub,
+                    "",
+                    None,
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "source pointer is only valid for ",
+                    sup,
+                    "",
+                    None,
+                );
+                err
+            }
+            infer::RelateParamBound(span, ty, opt_span) => {
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0477,
+                    "the type `{}` does not fulfill the required lifetime",
+                    self.ty_to_string(ty)
+                );
+                match *sub {
+                    ty::ReStatic => note_and_explain_region(
+                        self.tcx,
+                        &mut err,
+                        "type must satisfy ",
+                        sub,
+                        if opt_span.is_some() { " as required by this binding" } else { "" },
+                        opt_span,
+                    ),
+                    _ => note_and_explain_region(
+                        self.tcx,
+                        &mut err,
+                        "type must outlive ",
+                        sub,
+                        if opt_span.is_some() { " as required by this binding" } else { "" },
+                        opt_span,
+                    ),
+                }
+                err
+            }
+            infer::RelateRegionParamBound(span) => {
+                let mut err =
+                    struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "lifetime parameter instantiated with ",
+                    sup,
+                    "",
+                    None,
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "but lifetime parameter must outlive ",
+                    sub,
+                    "",
+                    None,
+                );
+                err
+            }
+            infer::DataBorrowed(ty, span) => {
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0490,
+                    "a value of type `{}` is borrowed for too long",
+                    self.ty_to_string(ty)
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "the type is valid for ",
+                    sub,
+                    "",
+                    None,
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "but the borrow lasts for ",
+                    sup,
+                    "",
+                    None,
+                );
+                err
+            }
+            infer::ReferenceOutlivesReferent(ty, span) => {
+                let mut err = struct_span_err!(
+                    self.tcx.sess,
+                    span,
+                    E0491,
+                    "in type `{}`, reference has a longer lifetime than the data it references",
+                    self.ty_to_string(ty)
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "the pointer is valid for ",
+                    sub,
+                    "",
+                    None,
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "but the referenced data is only valid for ",
+                    sup,
+                    "",
+                    None,
+                );
+                err
+            }
+            infer::CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => self
+                .report_extra_impl_obligation(
+                    span,
+                    impl_item_def_id,
+                    trait_item_def_id,
+                    &format!("`{}: {}`", sup, sub),
+                ),
+            infer::CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => {
+                let mut err = self.report_concrete_failure(*parent, sub, sup);
+
+                let trait_item_span = self.tcx.def_span(trait_item_def_id);
+                let item_name = self.tcx.item_name(impl_item_def_id.to_def_id());
+                err.span_label(
+                    trait_item_span,
+                    format!("definition of `{}` from trait", item_name),
+                );
+
+                let trait_predicates = self.tcx.explicit_predicates_of(trait_item_def_id);
+                let impl_predicates = self.tcx.explicit_predicates_of(impl_item_def_id);
+
+                let impl_predicates: rustc_data_structures::fx::FxHashSet<_> =
+                    impl_predicates.predicates.into_iter().map(|(pred, _)| pred).collect();
+                let clauses: Vec<_> = trait_predicates
+                    .predicates
+                    .into_iter()
+                    .filter(|&(pred, _)| !impl_predicates.contains(pred))
+                    .map(|(pred, _)| format!("{}", pred))
+                    .collect();
+
+                if !clauses.is_empty() {
+                    let generics = self.tcx.hir().get_generics(impl_item_def_id).unwrap();
+                    let where_clause_span = generics.tail_span_for_predicate_suggestion();
+
+                    let suggestion = format!(
+                        "{} {}",
+                        generics.add_where_or_trailing_comma(),
+                        clauses.join(", "),
+                    );
+                    err.span_suggestion(
+                        where_clause_span,
+                        &format!(
+                            "try copying {} from the trait",
+                            if clauses.len() > 1 { "these clauses" } else { "this clause" }
+                        ),
+                        suggestion,
+                        rustc_errors::Applicability::MaybeIncorrect,
+                    );
+                }
+
+                err
+            }
+            infer::AscribeUserTypeProvePredicate(span) => {
+                let mut err =
+                    struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied");
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "lifetime instantiated with ",
+                    sup,
+                    "",
+                    None,
+                );
+                note_and_explain_region(
+                    self.tcx,
+                    &mut err,
+                    "but lifetime must outlive ",
+                    sub,
+                    "",
+                    None,
+                );
+                err
+            }
+        }
+    }
+
+    pub(super) fn report_placeholder_failure(
+        &self,
+        placeholder_origin: SubregionOrigin<'tcx>,
+        sub: Region<'tcx>,
+        sup: Region<'tcx>,
+    ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+        // I can't think how to do better than this right now. -nikomatsakis
+        debug!(?placeholder_origin, ?sub, ?sup, "report_placeholder_failure");
+        match placeholder_origin {
+            infer::Subtype(box ref trace)
+                if matches!(
+                    &trace.cause.code().peel_derives(),
+                    ObligationCauseCode::BindingObligation(..)
+                        | ObligationCauseCode::ExprBindingObligation(..)
+                ) =>
+            {
+                // Hack to get around the borrow checker because trace.cause has an `Rc`.
+                if let ObligationCauseCode::BindingObligation(_, span)
+                | ObligationCauseCode::ExprBindingObligation(_, span, ..) =
+                    &trace.cause.code().peel_derives()
+                {
+                    let span = *span;
+                    let mut err = self.report_concrete_failure(placeholder_origin, sub, sup);
+                    err.span_note(span, "the lifetime requirement is introduced here");
+                    err
+                } else {
+                    unreachable!()
+                }
+            }
+            infer::Subtype(box trace) => {
+                let terr = TypeError::RegionsPlaceholderMismatch;
+                return self.report_and_explain_type_error(trace, terr);
+            }
+            _ => return self.report_concrete_failure(placeholder_origin, sub, sup),
+        }
+    }
+}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
new file mode 100644
index 00000000000..73b5a2cc4ad
--- /dev/null
+++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
@@ -0,0 +1,672 @@
+use hir::def::CtorKind;
+use hir::intravisit::{walk_expr, walk_stmt, Visitor};
+use rustc_data_structures::fx::FxIndexSet;
+use rustc_errors::{Applicability, Diagnostic};
+use rustc_hir as hir;
+use rustc_middle::traits::{
+    IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
+    StatementAsExpression,
+};
+use rustc_middle::ty::print::with_no_trimmed_paths;
+use rustc_middle::ty::{self as ty, Ty, TypeVisitable};
+use rustc_span::{sym, BytePos, Span};
+
+use crate::errors::SuggAddLetForLetChains;
+
+use super::TypeErrCtxt;
+
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
+    pub(super) fn suggest_remove_semi_or_return_binding(
+        &self,
+        err: &mut Diagnostic,
+        first_id: Option<hir::HirId>,
+        first_ty: Ty<'tcx>,
+        first_span: Span,
+        second_id: Option<hir::HirId>,
+        second_ty: Ty<'tcx>,
+        second_span: Span,
+    ) {
+        let remove_semicolon = [
+            (first_id, self.resolve_vars_if_possible(second_ty)),
+            (second_id, self.resolve_vars_if_possible(first_ty)),
+        ]
+        .into_iter()
+        .find_map(|(id, ty)| {
+            let hir::Node::Block(blk) = self.tcx.hir().get(id?) else { return None };
+            self.could_remove_semicolon(blk, ty)
+        });
+        match remove_semicolon {
+            Some((sp, StatementAsExpression::NeedsBoxing)) => {
+                err.multipart_suggestion(
+                    "consider removing this semicolon and boxing the expressions",
+                    vec![
+                        (first_span.shrink_to_lo(), "Box::new(".to_string()),
+                        (first_span.shrink_to_hi(), ")".to_string()),
+                        (second_span.shrink_to_lo(), "Box::new(".to_string()),
+                        (second_span.shrink_to_hi(), ")".to_string()),
+                        (sp, String::new()),
+                    ],
+                    Applicability::MachineApplicable,
+                );
+            }
+            Some((sp, StatementAsExpression::CorrectType)) => {
+                err.span_suggestion_short(
+                    sp,
+                    "consider removing this semicolon",
+                    "",
+                    Applicability::MachineApplicable,
+                );
+            }
+            None => {
+                for (id, ty) in [(first_id, second_ty), (second_id, first_ty)] {
+                    if let Some(id) = id
+                        && let hir::Node::Block(blk) = self.tcx.hir().get(id)
+                        && self.consider_returning_binding(blk, ty, err)
+                    {
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    pub(super) fn suggest_boxing_for_return_impl_trait(
+        &self,
+        err: &mut Diagnostic,
+        return_sp: Span,
+        arm_spans: impl Iterator<Item = Span>,
+    ) {
+        err.multipart_suggestion(
+            "you could change the return type to be a boxed trait object",
+            vec![
+                (return_sp.with_hi(return_sp.lo() + BytePos(4)), "Box<dyn".to_string()),
+                (return_sp.shrink_to_hi(), ">".to_string()),
+            ],
+            Applicability::MaybeIncorrect,
+        );
+        let sugg = arm_spans
+            .flat_map(|sp| {
+                [(sp.shrink_to_lo(), "Box::new(".to_string()), (sp.shrink_to_hi(), ")".to_string())]
+                    .into_iter()
+            })
+            .collect::<Vec<_>>();
+        err.multipart_suggestion(
+            "if you change the return type to expect trait objects, box the returned expressions",
+            sugg,
+            Applicability::MaybeIncorrect,
+        );
+    }
+
+    pub(super) fn suggest_tuple_pattern(
+        &self,
+        cause: &ObligationCause<'tcx>,
+        exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
+        diag: &mut Diagnostic,
+    ) {
+        // Heavily inspired by `FnCtxt::suggest_compatible_variants`, with
+        // some modifications due to that being in typeck and this being in infer.
+        if let ObligationCauseCode::Pattern { .. } = cause.code() {
+            if let ty::Adt(expected_adt, substs) = exp_found.expected.kind() {
+                let compatible_variants: Vec<_> = expected_adt
+                    .variants()
+                    .iter()
+                    .filter(|variant| {
+                        variant.fields.len() == 1 && variant.ctor_kind() == Some(CtorKind::Fn)
+                    })
+                    .filter_map(|variant| {
+                        let sole_field = &variant.fields[0];
+                        let sole_field_ty = sole_field.ty(self.tcx, substs);
+                        if self.same_type_modulo_infer(sole_field_ty, exp_found.found) {
+                            let variant_path =
+                                with_no_trimmed_paths!(self.tcx.def_path_str(variant.def_id));
+                            // FIXME #56861: DRYer prelude filtering
+                            if let Some(path) = variant_path.strip_prefix("std::prelude::") {
+                                if let Some((_, path)) = path.split_once("::") {
+                                    return Some(path.to_string());
+                                }
+                            }
+                            Some(variant_path)
+                        } else {
+                            None
+                        }
+                    })
+                    .collect();
+                match &compatible_variants[..] {
+                    [] => {}
+                    [variant] => {
+                        diag.multipart_suggestion_verbose(
+                            &format!("try wrapping the pattern in `{}`", variant),
+                            vec![
+                                (cause.span.shrink_to_lo(), format!("{}(", variant)),
+                                (cause.span.shrink_to_hi(), ")".to_string()),
+                            ],
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                    _ => {
+                        // More than one matching variant.
+                        diag.multipart_suggestions(
+                            &format!(
+                                "try wrapping the pattern in a variant of `{}`",
+                                self.tcx.def_path_str(expected_adt.did())
+                            ),
+                            compatible_variants.into_iter().map(|variant| {
+                                vec![
+                                    (cause.span.shrink_to_lo(), format!("{}(", variant)),
+                                    (cause.span.shrink_to_hi(), ")".to_string()),
+                                ]
+                            }),
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                }
+            }
+        }
+    }
+
+    /// A possible error is to forget to add `.await` when using futures:
+    ///
+    /// ```compile_fail,E0308
+    /// async fn make_u32() -> u32 {
+    ///     22
+    /// }
+    ///
+    /// fn take_u32(x: u32) {}
+    ///
+    /// async fn foo() {
+    ///     let x = make_u32();
+    ///     take_u32(x);
+    /// }
+    /// ```
+    ///
+    /// This routine checks if the found type `T` implements `Future<Output=U>` where `U` is the
+    /// expected type. If this is the case, and we are inside of an async body, it suggests adding
+    /// `.await` to the tail of the expression.
+    pub(super) fn suggest_await_on_expect_found(
+        &self,
+        cause: &ObligationCause<'tcx>,
+        exp_span: Span,
+        exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
+        diag: &mut Diagnostic,
+    ) {
+        debug!(
+            "suggest_await_on_expect_found: exp_span={:?}, expected_ty={:?}, found_ty={:?}",
+            exp_span, exp_found.expected, exp_found.found,
+        );
+
+        if let ObligationCauseCode::CompareImplItemObligation { .. } = cause.code() {
+            return;
+        }
+
+        match (
+            self.get_impl_future_output_ty(exp_found.expected),
+            self.get_impl_future_output_ty(exp_found.found),
+        ) {
+            (Some(exp), Some(found)) if self.same_type_modulo_infer(exp, found) => match cause
+                .code()
+            {
+                ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
+                    let then_span = self.find_block_span_from_hir_id(*then_id);
+                    diag.multipart_suggestion(
+                        "consider `await`ing on both `Future`s",
+                        vec![
+                            (then_span.shrink_to_hi(), ".await".to_string()),
+                            (exp_span.shrink_to_hi(), ".await".to_string()),
+                        ],
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
+                    prior_arms,
+                    ..
+                }) => {
+                    if let [.., arm_span] = &prior_arms[..] {
+                        diag.multipart_suggestion(
+                            "consider `await`ing on both `Future`s",
+                            vec![
+                                (arm_span.shrink_to_hi(), ".await".to_string()),
+                                (exp_span.shrink_to_hi(), ".await".to_string()),
+                            ],
+                            Applicability::MaybeIncorrect,
+                        );
+                    } else {
+                        diag.help("consider `await`ing on both `Future`s");
+                    }
+                }
+                _ => {
+                    diag.help("consider `await`ing on both `Future`s");
+                }
+            },
+            (_, Some(ty)) if self.same_type_modulo_infer(exp_found.expected, ty) => {
+                diag.span_suggestion_verbose(
+                    exp_span.shrink_to_hi(),
+                    "consider `await`ing on the `Future`",
+                    ".await",
+                    Applicability::MaybeIncorrect,
+                );
+            }
+            (Some(ty), _) if self.same_type_modulo_infer(ty, exp_found.found) => match cause.code()
+            {
+                ObligationCauseCode::Pattern { span: Some(then_span), .. } => {
+                    diag.span_suggestion_verbose(
+                        then_span.shrink_to_hi(),
+                        "consider `await`ing on the `Future`",
+                        ".await",
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                ObligationCauseCode::IfExpression(box IfExpressionCause { then_id, .. }) => {
+                    let then_span = self.find_block_span_from_hir_id(*then_id);
+                    diag.span_suggestion_verbose(
+                        then_span.shrink_to_hi(),
+                        "consider `await`ing on the `Future`",
+                        ".await",
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
+                    ref prior_arms,
+                    ..
+                }) => {
+                    diag.multipart_suggestion_verbose(
+                        "consider `await`ing on the `Future`",
+                        prior_arms
+                            .iter()
+                            .map(|arm| (arm.shrink_to_hi(), ".await".to_string()))
+                            .collect(),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                _ => {}
+            },
+            _ => {}
+        }
+    }
+
+    pub(super) fn suggest_accessing_field_where_appropriate(
+        &self,
+        cause: &ObligationCause<'tcx>,
+        exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
+        diag: &mut Diagnostic,
+    ) {
+        debug!(
+            "suggest_accessing_field_where_appropriate(cause={:?}, exp_found={:?})",
+            cause, exp_found
+        );
+        if let ty::Adt(expected_def, expected_substs) = exp_found.expected.kind() {
+            if expected_def.is_enum() {
+                return;
+            }
+
+            if let Some((name, ty)) = expected_def
+                .non_enum_variant()
+                .fields
+                .iter()
+                .filter(|field| field.vis.is_accessible_from(field.did, self.tcx))
+                .map(|field| (field.name, field.ty(self.tcx, expected_substs)))
+                .find(|(_, ty)| self.same_type_modulo_infer(*ty, exp_found.found))
+            {
+                if let ObligationCauseCode::Pattern { span: Some(span), .. } = *cause.code() {
+                    if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+                        let suggestion = if expected_def.is_struct() {
+                            format!("{}.{}", snippet, name)
+                        } else if expected_def.is_union() {
+                            format!("unsafe {{ {}.{} }}", snippet, name)
+                        } else {
+                            return;
+                        };
+                        diag.span_suggestion(
+                            span,
+                            &format!(
+                                "you might have meant to use field `{}` whose type is `{}`",
+                                name, ty
+                            ),
+                            suggestion,
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                }
+            }
+        }
+    }
+
+    /// When encountering a case where `.as_ref()` on a `Result` or `Option` would be appropriate,
+    /// suggests it.
+    pub(super) fn suggest_as_ref_where_appropriate(
+        &self,
+        span: Span,
+        exp_found: &ty::error::ExpectedFound<Ty<'tcx>>,
+        diag: &mut Diagnostic,
+    ) {
+        if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
+            && let Some(msg) = self.should_suggest_as_ref(exp_found.expected, exp_found.found)
+        {
+            diag.span_suggestion(
+                span,
+                msg,
+                // HACK: fix issue# 100605, suggesting convert from &Option<T> to Option<&T>, remove the extra `&`
+                format!("{}.as_ref()", snippet.trim_start_matches('&')),
+                Applicability::MachineApplicable,
+            );
+        }
+    }
+
+    pub fn should_suggest_as_ref(&self, expected: Ty<'tcx>, found: Ty<'tcx>) -> Option<&str> {
+        if let (ty::Adt(exp_def, exp_substs), ty::Ref(_, found_ty, _)) =
+            (expected.kind(), found.kind())
+        {
+            if let ty::Adt(found_def, found_substs) = *found_ty.kind() {
+                if exp_def == &found_def {
+                    let have_as_ref = &[
+                        (
+                            sym::Option,
+                            "you can convert from `&Option<T>` to `Option<&T>` using \
+                        `.as_ref()`",
+                        ),
+                        (
+                            sym::Result,
+                            "you can convert from `&Result<T, E>` to \
+                        `Result<&T, &E>` using `.as_ref()`",
+                        ),
+                    ];
+                    if let Some(msg) = have_as_ref.iter().find_map(|(name, msg)| {
+                        self.tcx.is_diagnostic_item(*name, exp_def.did()).then_some(msg)
+                    }) {
+                        let mut show_suggestion = true;
+                        for (exp_ty, found_ty) in
+                            std::iter::zip(exp_substs.types(), found_substs.types())
+                        {
+                            match *exp_ty.kind() {
+                                ty::Ref(_, exp_ty, _) => {
+                                    match (exp_ty.kind(), found_ty.kind()) {
+                                        (_, ty::Param(_))
+                                        | (_, ty::Infer(_))
+                                        | (ty::Param(_), _)
+                                        | (ty::Infer(_), _) => {}
+                                        _ if self.same_type_modulo_infer(exp_ty, found_ty) => {}
+                                        _ => show_suggestion = false,
+                                    };
+                                }
+                                ty::Param(_) | ty::Infer(_) => {}
+                                _ => show_suggestion = false,
+                            }
+                        }
+                        if show_suggestion {
+                            return Some(*msg);
+                        }
+                    }
+                }
+            }
+        }
+        None
+    }
+
+    /// Try to find code with pattern `if Some(..) = expr`
+    /// use a `visitor` to mark the `if` which its span contains given error span,
+    /// and then try to find a assignment in the `cond` part, which span is equal with error span
+    pub(super) fn suggest_let_for_letchains(
+        &self,
+        err: &mut Diagnostic,
+        cause: &ObligationCause<'_>,
+        span: Span,
+    ) {
+        let hir = self.tcx.hir();
+        let fn_hir_id = hir.get_parent_node(cause.body_id);
+        if let Some(node) = self.tcx.hir().find(fn_hir_id) &&
+            let hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Fn(_sig, _, body_id), ..
+                }) = node {
+        let body = hir.body(*body_id);
+
+        /// Find the if expression with given span
+        struct IfVisitor {
+            pub result: bool,
+            pub found_if: bool,
+            pub err_span: Span,
+        }
+
+        impl<'v> Visitor<'v> for IfVisitor {
+            fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
+                if self.result { return; }
+                match ex.kind {
+                    hir::ExprKind::If(cond, _, _) => {
+                        self.found_if = true;
+                        walk_expr(self, cond);
+                        self.found_if = false;
+                    }
+                    _ => walk_expr(self, ex),
+                }
+            }
+
+            fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
+                if let hir::StmtKind::Local(hir::Local {
+                        span, pat: hir::Pat{..}, ty: None, init: Some(_), ..
+                    }) = &ex.kind
+                    && self.found_if
+                    && span.eq(&self.err_span) {
+                        self.result = true;
+                }
+                walk_stmt(self, ex);
+            }
+
+            fn visit_body(&mut self, body: &'v hir::Body<'v>) {
+                hir::intravisit::walk_body(self, body);
+            }
+        }
+
+        let mut visitor = IfVisitor { err_span: span, found_if: false, result: false };
+        visitor.visit_body(&body);
+        if visitor.result {
+                err.subdiagnostic(SuggAddLetForLetChains{span: span.shrink_to_lo()});
+            }
+        }
+    }
+}
+
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
+    /// Be helpful when the user wrote `{... expr; }` and taking the `;` off
+    /// is enough to fix the error.
+    pub fn could_remove_semicolon(
+        &self,
+        blk: &'tcx hir::Block<'tcx>,
+        expected_ty: Ty<'tcx>,
+    ) -> Option<(Span, StatementAsExpression)> {
+        let blk = blk.innermost_block();
+        // Do not suggest if we have a tail expr.
+        if blk.expr.is_some() {
+            return None;
+        }
+        let last_stmt = blk.stmts.last()?;
+        let hir::StmtKind::Semi(ref last_expr) = last_stmt.kind else {
+            return None;
+        };
+        let last_expr_ty = self.typeck_results.as_ref()?.expr_ty_opt(*last_expr)?;
+        let needs_box = match (last_expr_ty.kind(), expected_ty.kind()) {
+            _ if last_expr_ty.references_error() => return None,
+            _ if self.same_type_modulo_infer(last_expr_ty, expected_ty) => {
+                StatementAsExpression::CorrectType
+            }
+            (ty::Opaque(last_def_id, _), ty::Opaque(exp_def_id, _))
+                if last_def_id == exp_def_id =>
+            {
+                StatementAsExpression::CorrectType
+            }
+            (ty::Opaque(last_def_id, last_bounds), ty::Opaque(exp_def_id, exp_bounds)) => {
+                debug!(
+                    "both opaque, likely future {:?} {:?} {:?} {:?}",
+                    last_def_id, last_bounds, exp_def_id, exp_bounds
+                );
+
+                let last_local_id = last_def_id.as_local()?;
+                let exp_local_id = exp_def_id.as_local()?;
+
+                match (
+                    &self.tcx.hir().expect_item(last_local_id).kind,
+                    &self.tcx.hir().expect_item(exp_local_id).kind,
+                ) {
+                    (
+                        hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: last_bounds, .. }),
+                        hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds: exp_bounds, .. }),
+                    ) if std::iter::zip(*last_bounds, *exp_bounds).all(|(left, right)| {
+                        match (left, right) {
+                            (
+                                hir::GenericBound::Trait(tl, ml),
+                                hir::GenericBound::Trait(tr, mr),
+                            ) if tl.trait_ref.trait_def_id() == tr.trait_ref.trait_def_id()
+                                && ml == mr =>
+                            {
+                                true
+                            }
+                            (
+                                hir::GenericBound::LangItemTrait(langl, _, _, argsl),
+                                hir::GenericBound::LangItemTrait(langr, _, _, argsr),
+                            ) if langl == langr => {
+                                // FIXME: consider the bounds!
+                                debug!("{:?} {:?}", argsl, argsr);
+                                true
+                            }
+                            _ => false,
+                        }
+                    }) =>
+                    {
+                        StatementAsExpression::NeedsBoxing
+                    }
+                    _ => StatementAsExpression::CorrectType,
+                }
+            }
+            _ => return None,
+        };
+        let span = if last_stmt.span.from_expansion() {
+            let mac_call = rustc_span::source_map::original_sp(last_stmt.span, blk.span);
+            self.tcx.sess.source_map().mac_call_stmt_semi_span(mac_call)?
+        } else {
+            last_stmt.span.with_lo(last_stmt.span.hi() - BytePos(1))
+        };
+        Some((span, needs_box))
+    }
+
+    /// Suggest returning a local binding with a compatible type if the block
+    /// has no return expression.
+    pub fn consider_returning_binding(
+        &self,
+        blk: &'tcx hir::Block<'tcx>,
+        expected_ty: Ty<'tcx>,
+        err: &mut Diagnostic,
+    ) -> bool {
+        let blk = blk.innermost_block();
+        // Do not suggest if we have a tail expr.
+        if blk.expr.is_some() {
+            return false;
+        }
+        let mut shadowed = FxIndexSet::default();
+        let mut candidate_idents = vec![];
+        let mut find_compatible_candidates = |pat: &hir::Pat<'_>| {
+            if let hir::PatKind::Binding(_, hir_id, ident, _) = &pat.kind
+                && let Some(pat_ty) = self
+                    .typeck_results
+                    .as_ref()
+                    .and_then(|typeck_results| typeck_results.node_type_opt(*hir_id))
+            {
+                let pat_ty = self.resolve_vars_if_possible(pat_ty);
+                if self.same_type_modulo_infer(pat_ty, expected_ty)
+                    && !(pat_ty, expected_ty).references_error()
+                    && shadowed.insert(ident.name)
+                {
+                    candidate_idents.push((*ident, pat_ty));
+                }
+            }
+            true
+        };
+
+        let hir = self.tcx.hir();
+        for stmt in blk.stmts.iter().rev() {
+            let hir::StmtKind::Local(local) = &stmt.kind else { continue; };
+            local.pat.walk(&mut find_compatible_candidates);
+        }
+        match hir.find(hir.get_parent_node(blk.hir_id)) {
+            Some(hir::Node::Expr(hir::Expr { hir_id, .. })) => {
+                match hir.find(hir.get_parent_node(*hir_id)) {
+                    Some(hir::Node::Arm(hir::Arm { pat, .. })) => {
+                        pat.walk(&mut find_compatible_candidates);
+                    }
+                    Some(
+                        hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, _, body), .. })
+                        | hir::Node::ImplItem(hir::ImplItem {
+                            kind: hir::ImplItemKind::Fn(_, body),
+                            ..
+                        })
+                        | hir::Node::TraitItem(hir::TraitItem {
+                            kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body)),
+                            ..
+                        })
+                        | hir::Node::Expr(hir::Expr {
+                            kind: hir::ExprKind::Closure(hir::Closure { body, .. }),
+                            ..
+                        }),
+                    ) => {
+                        for param in hir.body(*body).params {
+                            param.pat.walk(&mut find_compatible_candidates);
+                        }
+                    }
+                    Some(hir::Node::Expr(hir::Expr {
+                        kind:
+                            hir::ExprKind::If(
+                                hir::Expr { kind: hir::ExprKind::Let(let_), .. },
+                                then_block,
+                                _,
+                            ),
+                        ..
+                    })) if then_block.hir_id == *hir_id => {
+                        let_.pat.walk(&mut find_compatible_candidates);
+                    }
+                    _ => {}
+                }
+            }
+            _ => {}
+        }
+
+        match &candidate_idents[..] {
+            [(ident, _ty)] => {
+                let sm = self.tcx.sess.source_map();
+                if let Some(stmt) = blk.stmts.last() {
+                    let stmt_span = sm.stmt_span(stmt.span, blk.span);
+                    let sugg = if sm.is_multiline(blk.span)
+                        && let Some(spacing) = sm.indentation_before(stmt_span)
+                    {
+                        format!("\n{spacing}{ident}")
+                    } else {
+                        format!(" {ident}")
+                    };
+                    err.span_suggestion_verbose(
+                        stmt_span.shrink_to_hi(),
+                        format!("consider returning the local binding `{ident}`"),
+                        sugg,
+                        Applicability::MaybeIncorrect,
+                    );
+                } else {
+                    let sugg = if sm.is_multiline(blk.span)
+                        && let Some(spacing) = sm.indentation_before(blk.span.shrink_to_lo())
+                    {
+                        format!("\n{spacing}    {ident}\n{spacing}")
+                    } else {
+                        format!(" {ident} ")
+                    };
+                    let left_span = sm.span_through_char(blk.span, '{').shrink_to_hi();
+                    err.span_suggestion_verbose(
+                        sm.span_extend_while(left_span, |c| c.is_whitespace()).unwrap_or(left_span),
+                        format!("consider returning the local binding `{ident}`"),
+                        sugg,
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                true
+            }
+            values if (1..3).contains(&values.len()) => {
+                let spans = values.iter().map(|(ident, _)| ident.span).collect::<Vec<_>>();
+                err.span_note(spans, "consider returning one of these bindings");
+                true
+            }
+            _ => false,
+        }
+    }
+}
diff --git a/compiler/rustc_infer/src/infer/note.rs b/compiler/rustc_infer/src/infer/note.rs
new file mode 100644
index 00000000000..2ccbd164faa
--- /dev/null
+++ b/compiler/rustc_infer/src/infer/note.rs
@@ -0,0 +1,203 @@
+impl<'tcx> TypeErrCtxt<'_, 'tcx> {
+    fn note_error_origin(
+        &self,
+        err: &mut Diagnostic,
+        cause: &ObligationCause<'tcx>,
+        exp_found: Option<ty::error::ExpectedFound<Ty<'tcx>>>,
+        terr: TypeError<'tcx>,
+    ) {
+        match *cause.code() {
+            ObligationCauseCode::Pattern { origin_expr: true, span: Some(span), root_ty } => {
+                let ty = self.resolve_vars_if_possible(root_ty);
+                if !matches!(ty.kind(), ty::Infer(ty::InferTy::TyVar(_) | ty::InferTy::FreshTy(_)))
+                {
+                    // don't show type `_`
+                    if span.desugaring_kind() == Some(DesugaringKind::ForLoop)
+                        && let ty::Adt(def, substs) = ty.kind()
+                        && Some(def.did()) == self.tcx.get_diagnostic_item(sym::Option)
+                    {
+                        err.span_label(span, format!("this is an iterator with items of type `{}`", substs.type_at(0)));
+                    } else {
+                    err.span_label(span, format!("this expression has type `{}`", ty));
+                }
+                }
+                if let Some(ty::error::ExpectedFound { found, .. }) = exp_found
+                    && ty.is_box() && ty.boxed_ty() == found
+                    && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
+                {
+                    err.span_suggestion(
+                        span,
+                        "consider dereferencing the boxed value",
+                        format!("*{}", snippet),
+                        Applicability::MachineApplicable,
+                    );
+                }
+            }
+            ObligationCauseCode::Pattern { origin_expr: false, span: Some(span), .. } => {
+                err.span_label(span, "expected due to this");
+            }
+            ObligationCauseCode::MatchExpressionArm(box MatchExpressionArmCause {
+                arm_block_id,
+                arm_span,
+                arm_ty,
+                prior_arm_block_id,
+                prior_arm_span,
+                prior_arm_ty,
+                source,
+                ref prior_arms,
+                scrut_hir_id,
+                opt_suggest_box_span,
+                scrut_span,
+                ..
+            }) => match source {
+                hir::MatchSource::TryDesugar => {
+                    if let Some(ty::error::ExpectedFound { expected, .. }) = exp_found {
+                        let scrut_expr = self.tcx.hir().expect_expr(scrut_hir_id);
+                        let scrut_ty = if let hir::ExprKind::Call(_, args) = &scrut_expr.kind {
+                            let arg_expr = args.first().expect("try desugaring call w/out arg");
+                            self.typeck_results.as_ref().and_then(|typeck_results| {
+                                typeck_results.expr_ty_opt(arg_expr)
+                            })
+                        } else {
+                            bug!("try desugaring w/out call expr as scrutinee");
+                        };
+
+                        match scrut_ty {
+                            Some(ty) if expected == ty => {
+                                let source_map = self.tcx.sess.source_map();
+                                err.span_suggestion(
+                                    source_map.end_point(cause.span),
+                                    "try removing this `?`",
+                                    "",
+                                    Applicability::MachineApplicable,
+                                );
+                            }
+                            _ => {}
+                        }
+                    }
+                }
+                _ => {
+                    // `prior_arm_ty` can be `!`, `expected` will have better info when present.
+                    let t = self.resolve_vars_if_possible(match exp_found {
+                        Some(ty::error::ExpectedFound { expected, .. }) => expected,
+                        _ => prior_arm_ty,
+                    });
+                    let source_map = self.tcx.sess.source_map();
+                    let mut any_multiline_arm = source_map.is_multiline(arm_span);
+                    if prior_arms.len() <= 4 {
+                        for sp in prior_arms {
+                            any_multiline_arm |= source_map.is_multiline(*sp);
+                            err.span_label(*sp, format!("this is found to be of type `{}`", t));
+                        }
+                    } else if let Some(sp) = prior_arms.last() {
+                        any_multiline_arm |= source_map.is_multiline(*sp);
+                        err.span_label(
+                            *sp,
+                            format!("this and all prior arms are found to be of type `{}`", t),
+                        );
+                    }
+                    let outer_error_span = if any_multiline_arm {
+                        // Cover just `match` and the scrutinee expression, not
+                        // the entire match body, to reduce diagram noise.
+                        cause.span.shrink_to_lo().to(scrut_span)
+                    } else {
+                        cause.span
+                    };
+                    let msg = "`match` arms have incompatible types";
+                    err.span_label(outer_error_span, msg);
+                    self.suggest_remove_semi_or_return_binding(
+                        err,
+                        prior_arm_block_id,
+                        prior_arm_ty,
+                        prior_arm_span,
+                        arm_block_id,
+                        arm_ty,
+                        arm_span,
+                    );
+                    if let Some(ret_sp) = opt_suggest_box_span {
+                        // Get return type span and point to it.
+                        self.suggest_boxing_for_return_impl_trait(
+                            err,
+                            ret_sp,
+                            prior_arms.iter().chain(std::iter::once(&arm_span)).map(|s| *s),
+                        );
+                    }
+                }
+            },
+            ObligationCauseCode::IfExpression(box IfExpressionCause {
+                then_id,
+                else_id,
+                then_ty,
+                else_ty,
+                outer_span,
+                opt_suggest_box_span,
+            }) => {
+                let then_span = self.find_block_span_from_hir_id(then_id);
+                let else_span = self.find_block_span_from_hir_id(else_id);
+                err.span_label(then_span, "expected because of this");
+                if let Some(sp) = outer_span {
+                    err.span_label(sp, "`if` and `else` have incompatible types");
+                }
+                self.suggest_remove_semi_or_return_binding(
+                    err,
+                    Some(then_id),
+                    then_ty,
+                    then_span,
+                    Some(else_id),
+                    else_ty,
+                    else_span,
+                );
+                if let Some(ret_sp) = opt_suggest_box_span {
+                    self.suggest_boxing_for_return_impl_trait(
+                        err,
+                        ret_sp,
+                        [then_span, else_span].into_iter(),
+                    );
+                }
+            }
+            ObligationCauseCode::LetElse => {
+                err.help("try adding a diverging expression, such as `return` or `panic!(..)`");
+                err.help("...or use `match` instead of `let...else`");
+            }
+            _ => {
+                if let ObligationCauseCode::BindingObligation(_, span)
+                | ObligationCauseCode::ExprBindingObligation(_, span, ..)
+                = cause.code().peel_derives()
+                    && let TypeError::RegionsPlaceholderMismatch = terr
+                {
+                    err.span_note( * span,
+                    "the lifetime requirement is introduced here");
+                }
+            }
+        }
+    }
+}
+
+impl<'tcx> InferCtxt<'tcx> {
+    /// Given a [`hir::Block`], get the span of its last expression or
+    /// statement, peeling off any inner blocks.
+    pub fn find_block_span(&self, block: &'tcx hir::Block<'tcx>) -> Span {
+        let block = block.innermost_block();
+        if let Some(expr) = &block.expr {
+            expr.span
+        } else if let Some(stmt) = block.stmts.last() {
+            // possibly incorrect trailing `;` in the else arm
+            stmt.span
+        } else {
+            // empty block; point at its entirety
+            block.span
+        }
+    }
+
+    /// Given a [`hir::HirId`] for a block, get the span of its last expression
+    /// or statement, peeling off any inner blocks.
+    pub fn find_block_span_from_hir_id(&self, hir_id: hir::HirId) -> Span {
+        match self.tcx.hir().get(hir_id) {
+            hir::Node::Block(blk) => self.find_block_span(blk),
+            // The parser was in a weird state if either of these happen, but
+            // it's better not to panic.
+            hir::Node::Expr(e) => e.span,
+            _ => rustc_span::DUMMY_SP,
+        }
+    }
+}
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index f75c8669fa1..89d9450cf4e 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -158,7 +158,7 @@ pub fn create_resolver(
     sess: Lrc<Session>,
     metadata_loader: Box<MetadataLoaderDyn>,
     krate: &ast::Crate,
-    crate_name: &str,
+    crate_name: Symbol,
 ) -> BoxedResolver {
     trace!("create_resolver");
     BoxedResolver::new(sess, move |sess, resolver_arenas| {
@@ -171,7 +171,7 @@ pub fn register_plugins<'a>(
     metadata_loader: &'a dyn MetadataLoader,
     register_lints: impl Fn(&Session, &mut LintStore),
     mut krate: ast::Crate,
-    crate_name: &str,
+    crate_name: Symbol,
 ) -> Result<(ast::Crate, LintStore)> {
     krate = sess.time("attributes_injection", || {
         rustc_builtin_macros::cmdline_attrs::inject(
@@ -228,19 +228,21 @@ fn pre_expansion_lint<'a>(
     lint_store: &LintStore,
     registered_tools: &RegisteredTools,
     check_node: impl EarlyCheckNode<'a>,
-    node_name: &str,
+    node_name: Symbol,
 ) {
-    sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name).run(|| {
-        rustc_lint::check_ast_node(
-            sess,
-            true,
-            lint_store,
-            registered_tools,
-            None,
-            rustc_lint::BuiltinCombinedPreExpansionLintPass::new(),
-            check_node,
-        );
-    });
+    sess.prof.generic_activity_with_arg("pre_AST_expansion_lint_checks", node_name.as_str()).run(
+        || {
+            rustc_lint::check_ast_node(
+                sess,
+                true,
+                lint_store,
+                registered_tools,
+                None,
+                rustc_lint::BuiltinCombinedPreExpansionLintPass::new(),
+                check_node,
+            );
+        },
+    );
 }
 
 // Cannot implement directly for `LintStore` due to trait coherence.
@@ -254,7 +256,7 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> {
         node_id: ast::NodeId,
         attrs: &[ast::Attribute],
         items: &[rustc_ast::ptr::P<ast::Item>],
-        name: &str,
+        name: Symbol,
     ) {
         pre_expansion_lint(sess, self.0, registered_tools, (node_id, attrs, items), name);
     }
@@ -268,7 +270,7 @@ pub fn configure_and_expand(
     sess: &Session,
     lint_store: &LintStore,
     mut krate: ast::Crate,
-    crate_name: &str,
+    crate_name: Symbol,
     resolver: &mut Resolver<'_>,
 ) -> Result<ast::Crate> {
     trace!("configure_and_expand");
@@ -462,7 +464,7 @@ fn generated_output_paths(
     sess: &Session,
     outputs: &OutputFilenames,
     exact_name: bool,
-    crate_name: &str,
+    crate_name: Symbol,
 ) -> Vec<PathBuf> {
     let mut out_filenames = Vec::new();
     for output_type in sess.opts.output_types.keys() {
@@ -661,7 +663,7 @@ pub fn prepare_outputs(
     compiler: &Compiler,
     krate: &ast::Crate,
     boxed_resolver: &RefCell<BoxedResolver>,
-    crate_name: &str,
+    crate_name: Symbol,
 ) -> Result<OutputFilenames> {
     let _timer = sess.timer("prepare_outputs");
 
@@ -771,7 +773,7 @@ pub fn create_global_ctxt<'tcx>(
     dep_graph: DepGraph,
     resolver: Rc<RefCell<BoxedResolver>>,
     outputs: OutputFilenames,
-    crate_name: &str,
+    crate_name: Symbol,
     queries: &'tcx OnceCell<TcxQueries<'tcx>>,
     global_ctxt: &'tcx OnceCell<GlobalCtxt<'tcx>>,
     arena: &'tcx WorkerLocal<Arena<'tcx>>,
@@ -803,9 +805,9 @@ pub fn create_global_ctxt<'tcx>(
     });
 
     let ty::ResolverOutputs {
-        definitions,
         global_ctxt: untracked_resolutions,
         ast_lowering: untracked_resolver_for_lowering,
+        untracked,
     } = resolver_outputs;
 
     let gcx = sess.time("setup_global_ctxt", || {
@@ -815,8 +817,8 @@ pub fn create_global_ctxt<'tcx>(
                 lint_store,
                 arena,
                 hir_arena,
-                definitions,
                 untracked_resolutions,
+                untracked,
                 krate,
                 dep_graph,
                 queries.on_disk_cache.as_ref().map(OnDiskCache::as_dyn),
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index f5ddd647b24..39e1f2204b0 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -17,6 +17,7 @@ use rustc_query_impl::Queries as TcxQueries;
 use rustc_session::config::{self, OutputFilenames, OutputType};
 use rustc_session::{output::find_crate_name, Session};
 use rustc_span::symbol::sym;
+use rustc_span::Symbol;
 use std::any::Any;
 use std::cell::{Ref, RefCell, RefMut};
 use std::rc::Rc;
@@ -74,7 +75,7 @@ pub struct Queries<'tcx> {
 
     dep_graph_future: Query<Option<DepGraphFuture>>,
     parse: Query<ast::Crate>,
-    crate_name: Query<String>,
+    crate_name: Query<Symbol>,
     register_plugins: Query<(ast::Crate, Lrc<LintStore>)>,
     expansion: Query<(Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>,
     dep_graph: Query<DepGraph>,
@@ -135,7 +136,7 @@ impl<'tcx> Queries<'tcx> {
                 &*self.codegen_backend().metadata_loader(),
                 self.compiler.register_lints.as_deref().unwrap_or_else(|| empty),
                 krate,
-                &crate_name,
+                crate_name,
             )?;
 
             // Compute the dependency graph (in the background). We want to do
@@ -149,7 +150,7 @@ impl<'tcx> Queries<'tcx> {
         })
     }
 
-    pub fn crate_name(&self) -> Result<&Query<String>> {
+    pub fn crate_name(&self) -> Result<&Query<Symbol>> {
         self.crate_name.compute(|| {
             Ok({
                 let parse_result = self.parse()?;
@@ -165,7 +166,7 @@ impl<'tcx> Queries<'tcx> {
     ) -> Result<&Query<(Lrc<ast::Crate>, Rc<RefCell<BoxedResolver>>, Lrc<LintStore>)>> {
         trace!("expansion");
         self.expansion.compute(|| {
-            let crate_name = self.crate_name()?.peek().clone();
+            let crate_name = *self.crate_name()?.peek();
             let (krate, lint_store) = self.register_plugins()?.take();
             let _timer = self.session().timer("configure_and_expand");
             let sess = self.session();
@@ -173,10 +174,10 @@ impl<'tcx> Queries<'tcx> {
                 sess.clone(),
                 self.codegen_backend().metadata_loader(),
                 &krate,
-                &crate_name,
+                crate_name,
             );
             let krate = resolver.access(|resolver| {
-                passes::configure_and_expand(sess, &lint_store, krate, &crate_name, resolver)
+                passes::configure_and_expand(sess, &lint_store, krate, crate_name, resolver)
             })?;
             Ok((Lrc::new(krate), Rc::new(RefCell::new(resolver)), lint_store))
         })
@@ -201,20 +202,20 @@ impl<'tcx> Queries<'tcx> {
     pub fn prepare_outputs(&self) -> Result<&Query<OutputFilenames>> {
         self.prepare_outputs.compute(|| {
             let (krate, boxed_resolver, _) = &*self.expansion()?.peek();
-            let crate_name = self.crate_name()?.peek();
+            let crate_name = *self.crate_name()?.peek();
             passes::prepare_outputs(
                 self.session(),
                 self.compiler,
                 krate,
                 &*boxed_resolver,
-                &crate_name,
+                crate_name,
             )
         })
     }
 
     pub fn global_ctxt(&'tcx self) -> Result<&Query<QueryContext<'tcx>>> {
         self.global_ctxt.compute(|| {
-            let crate_name = self.crate_name()?.peek().clone();
+            let crate_name = *self.crate_name()?.peek();
             let outputs = self.prepare_outputs()?.take();
             let dep_graph = self.dep_graph()?.peek().clone();
             let (krate, resolver, lint_store) = self.expansion()?.take();
@@ -225,7 +226,7 @@ impl<'tcx> Queries<'tcx> {
                 dep_graph,
                 resolver,
                 outputs,
-                &crate_name,
+                crate_name,
                 &self.queries,
                 &self.gcx,
                 &self.arena,
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index d0d34d8d2b4..0932eee9237 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -53,7 +53,8 @@ use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, InnerSpan, Span};
 use rustc_target::abi::{Abi, VariantIdx};
-use rustc_trait_selection::traits::{self, misc::can_type_implement_copy};
+use rustc_trait_selection::infer::{InferCtxtExt, TyCtxtInferExt};
+use rustc_trait_selection::traits::{self, misc::can_type_implement_copy, EvaluationResult};
 
 use crate::nonstandard_style::{method_context, MethodLateContext};
 
@@ -96,6 +97,7 @@ fn pierce_parens(mut expr: &ast::Expr) -> &ast::Expr {
 }
 
 impl EarlyLintPass for WhileTrue {
+    #[inline]
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
         if let ast::ExprKind::While(cond, _, label) = &e.kind
             && let cond = pierce_parens(cond)
@@ -360,6 +362,7 @@ impl EarlyLintPass for UnsafeCode {
         }
     }
 
+    #[inline]
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
         if let ast::ExprKind::Block(ref blk, _) = e.kind {
             // Don't warn about generated blocks; that'll just pollute the output.
@@ -582,6 +585,7 @@ impl MissingDoc {
 }
 
 impl<'tcx> LateLintPass<'tcx> for MissingDoc {
+    #[inline]
     fn enter_lint_attrs(&mut self, _cx: &LateContext<'_>, attrs: &[ast::Attribute]) {
         let doc_hidden = self.doc_hidden()
             || attrs.iter().any(|attr| {
@@ -750,10 +754,39 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
         if def.has_dtor(cx.tcx) {
             return;
         }
+
+        // If the type contains a raw pointer, it may represent something like a handle,
+        // and recommending Copy might be a bad idea.
+        for field in def.all_fields() {
+            let did = field.did;
+            if cx.tcx.type_of(did).is_unsafe_ptr() {
+                return;
+            }
+        }
         let param_env = ty::ParamEnv::empty();
         if ty.is_copy_modulo_regions(cx.tcx, param_env) {
             return;
         }
+
+        // We shouldn't recommend implementing `Copy` on stateful things,
+        // such as iterators.
+        if let Some(iter_trait) = cx.tcx.get_diagnostic_item(sym::Iterator) {
+            if cx.tcx.infer_ctxt().build().type_implements_trait(iter_trait, [ty], param_env)
+                == EvaluationResult::EvaluatedToOk
+            {
+                return;
+            }
+        }
+
+        // Default value of clippy::trivially_copy_pass_by_ref
+        const MAX_SIZE: u64 = 256;
+
+        if let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()) {
+            if size > MAX_SIZE {
+                return;
+            }
+        }
+
         if can_type_implement_copy(
             cx.tcx,
             param_env,
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index 52363b0be2d..5d81370c35a 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -37,7 +37,9 @@ pub struct EarlyContextAndPasses<'a> {
 }
 
 impl<'a> EarlyContextAndPasses<'a> {
-    fn check_id(&mut self, id: ast::NodeId) {
+    // This always-inlined function is for the hot call site.
+    #[inline(always)]
+    fn inlined_check_id(&mut self, id: ast::NodeId) {
         for early_lint in self.context.buffered.take(id) {
             let BufferedEarlyLint { span, msg, node_id: _, lint_id, diagnostic } = early_lint;
             self.context.lookup_with_diagnostics(
@@ -50,6 +52,11 @@ impl<'a> EarlyContextAndPasses<'a> {
         }
     }
 
+    // This non-inlined function is for the cold call sites.
+    fn check_id(&mut self, id: ast::NodeId) {
+        self.inlined_check_id(id)
+    }
+
     /// Merge the lints specified by any lint attributes into the
     /// current lint context, call the provided function, then reset the
     /// lints in effect to their previous state.
@@ -61,7 +68,7 @@ impl<'a> EarlyContextAndPasses<'a> {
         debug!(?id);
         let push = self.context.builder.push(attrs, is_crate_node, None);
 
-        self.check_id(id);
+        self.inlined_check_id(id);
         debug!("early context: enter_attrs({:?})", attrs);
         run_early_passes!(self, enter_lint_attrs, attrs);
         f(self);
diff --git a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
index 7106e75dba2..dc2f5c0e296 100644
--- a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
+++ b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
@@ -121,6 +121,7 @@ impl EarlyLintPass for HiddenUnicodeCodepoints {
         }
     }
 
+    #[inline]
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
         // byte strings are already handled well enough by `EscapeError::NonAsciiCharInByteString`
         match &expr.kind {
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 10bae36e0fd..1990a74841b 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -127,6 +127,7 @@ fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
     late::late_lint_mod(tcx, module_def_id, BuiltinCombinedModuleLateLintPass::new());
 }
 
+// See the comment on `BuiltinCombinedEarlyLintPass`, which is similar.
 early_lint_methods!(
     declare_combined_early_lint_pass,
     [
@@ -137,6 +138,9 @@ early_lint_methods!(
     ]
 );
 
+// Declare `BuiltinCombinedEarlyLintPass`, a lint pass that combines multiple
+// lint passes into a single pass for maximum speed. Each `check_foo` method
+// within this pass simply calls `check_foo` once per listed lint.
 early_lint_methods!(
     declare_combined_early_lint_pass,
     [
@@ -162,7 +166,9 @@ early_lint_methods!(
     ]
 );
 
-// FIXME: Make a separate lint type which do not require typeck tables
+// FIXME: Make a separate lint type which does not require typeck tables.
+
+// See the comment on `BuiltinCombinedEarlyLintPass`, which is similar.
 late_lint_methods!(
     declare_combined_late_lint_pass,
     [
@@ -179,10 +185,10 @@ late_lint_methods!(
             // Keeps a global list of foreign declarations.
             ClashingExternDeclarations: ClashingExternDeclarations::new(),
         ]
-    ],
-    ['tcx]
+    ]
 );
 
+// See the comment on `BuiltinCombinedEarlyLintPass`, which is similar.
 late_lint_methods!(
     declare_combined_late_lint_pass,
     [
@@ -229,8 +235,7 @@ late_lint_methods!(
             NamedAsmLabels: NamedAsmLabels,
             OpaqueHiddenInferredBound: OpaqueHiddenInferredBound,
         ]
-    ],
-    ['tcx]
+    ]
 );
 
 pub fn new_lint_store(internal_lints: bool) -> LintStore {
diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs
index 2f53986139e..00922cef384 100644
--- a/compiler/rustc_lint/src/passes.rs
+++ b/compiler/rustc_lint/src/passes.rs
@@ -9,49 +9,49 @@ use rustc_span::Span;
 
 #[macro_export]
 macro_rules! late_lint_methods {
-    ($macro:path, $args:tt, [$hir:tt]) => (
-        $macro!($args, [$hir], [
-            fn check_body(a: &$hir hir::Body<$hir>);
-            fn check_body_post(a: &$hir hir::Body<$hir>);
+    ($macro:path, $args:tt) => (
+        $macro!($args, [
+            fn check_body(a: &'tcx hir::Body<'tcx>);
+            fn check_body_post(a: &'tcx hir::Body<'tcx>);
             fn check_crate();
             fn check_crate_post();
-            fn check_mod(a: &$hir hir::Mod<$hir>, b: hir::HirId);
-            fn check_foreign_item(a: &$hir hir::ForeignItem<$hir>);
-            fn check_item(a: &$hir hir::Item<$hir>);
-            fn check_item_post(a: &$hir hir::Item<$hir>);
-            fn check_local(a: &$hir hir::Local<$hir>);
-            fn check_block(a: &$hir hir::Block<$hir>);
-            fn check_block_post(a: &$hir hir::Block<$hir>);
-            fn check_stmt(a: &$hir hir::Stmt<$hir>);
-            fn check_arm(a: &$hir hir::Arm<$hir>);
-            fn check_pat(a: &$hir hir::Pat<$hir>);
-            fn check_expr(a: &$hir hir::Expr<$hir>);
-            fn check_expr_post(a: &$hir hir::Expr<$hir>);
-            fn check_ty(a: &$hir hir::Ty<$hir>);
-            fn check_generic_param(a: &$hir hir::GenericParam<$hir>);
-            fn check_generics(a: &$hir hir::Generics<$hir>);
-            fn check_poly_trait_ref(a: &$hir hir::PolyTraitRef<$hir>);
+            fn check_mod(a: &'tcx hir::Mod<'tcx>, b: hir::HirId);
+            fn check_foreign_item(a: &'tcx hir::ForeignItem<'tcx>);
+            fn check_item(a: &'tcx hir::Item<'tcx>);
+            fn check_item_post(a: &'tcx hir::Item<'tcx>);
+            fn check_local(a: &'tcx hir::Local<'tcx>);
+            fn check_block(a: &'tcx hir::Block<'tcx>);
+            fn check_block_post(a: &'tcx hir::Block<'tcx>);
+            fn check_stmt(a: &'tcx hir::Stmt<'tcx>);
+            fn check_arm(a: &'tcx hir::Arm<'tcx>);
+            fn check_pat(a: &'tcx hir::Pat<'tcx>);
+            fn check_expr(a: &'tcx hir::Expr<'tcx>);
+            fn check_expr_post(a: &'tcx hir::Expr<'tcx>);
+            fn check_ty(a: &'tcx hir::Ty<'tcx>);
+            fn check_generic_param(a: &'tcx hir::GenericParam<'tcx>);
+            fn check_generics(a: &'tcx hir::Generics<'tcx>);
+            fn check_poly_trait_ref(a: &'tcx hir::PolyTraitRef<'tcx>);
             fn check_fn(
-                a: rustc_hir::intravisit::FnKind<$hir>,
-                b: &$hir hir::FnDecl<$hir>,
-                c: &$hir hir::Body<$hir>,
+                a: rustc_hir::intravisit::FnKind<'tcx>,
+                b: &'tcx hir::FnDecl<'tcx>,
+                c: &'tcx hir::Body<'tcx>,
                 d: Span,
                 e: hir::HirId);
-            fn check_trait_item(a: &$hir hir::TraitItem<$hir>);
-            fn check_impl_item(a: &$hir hir::ImplItem<$hir>);
-            fn check_impl_item_post(a: &$hir hir::ImplItem<$hir>);
-            fn check_struct_def(a: &$hir hir::VariantData<$hir>);
-            fn check_field_def(a: &$hir hir::FieldDef<$hir>);
-            fn check_variant(a: &$hir hir::Variant<$hir>);
-            fn check_path(a: &hir::Path<$hir>, b: hir::HirId);
-            fn check_attribute(a: &$hir ast::Attribute);
+            fn check_trait_item(a: &'tcx hir::TraitItem<'tcx>);
+            fn check_impl_item(a: &'tcx hir::ImplItem<'tcx>);
+            fn check_impl_item_post(a: &'tcx hir::ImplItem<'tcx>);
+            fn check_struct_def(a: &'tcx hir::VariantData<'tcx>);
+            fn check_field_def(a: &'tcx hir::FieldDef<'tcx>);
+            fn check_variant(a: &'tcx hir::Variant<'tcx>);
+            fn check_path(a: &hir::Path<'tcx>, b: hir::HirId);
+            fn check_attribute(a: &'tcx ast::Attribute);
 
             /// Called when entering a syntax node that can have lint attributes such
             /// as `#[allow(...)]`. Called with *all* the attributes of that node.
-            fn enter_lint_attrs(a: &$hir [ast::Attribute]);
+            fn enter_lint_attrs(a: &'tcx [ast::Attribute]);
 
             /// Counterpart to `enter_lint_attrs`.
-            fn exit_lint_attrs(a: &$hir [ast::Attribute]);
+            fn exit_lint_attrs(a: &'tcx [ast::Attribute]);
         ]);
     )
 }
@@ -66,21 +66,23 @@ macro_rules! late_lint_methods {
 // contains a few lint-specific methods with no equivalent in `Visitor`.
 
 macro_rules! declare_late_lint_pass {
-    ([], [$hir:tt], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
-        pub trait LateLintPass<$hir>: LintPass {
-            $(#[inline(always)] fn $name(&mut self, _: &LateContext<$hir>, $(_: $arg),*) {})*
+    ([], [$($(#[$attr:meta])* fn $name:ident($($param:ident: $arg:ty),*);)*]) => (
+        pub trait LateLintPass<'tcx>: LintPass {
+            $(#[inline(always)] fn $name(&mut self, _: &LateContext<'tcx>, $(_: $arg),*) {})*
         }
     )
 }
 
-late_lint_methods!(declare_late_lint_pass, [], ['tcx]);
+// Declare the `LateLintPass` trait, which contains empty default definitions
+// for all the `check_*` methods.
+late_lint_methods!(declare_late_lint_pass, []);
 
 impl LateLintPass<'_> for HardwiredLints {}
 
 #[macro_export]
 macro_rules! expand_combined_late_lint_pass_method {
-    ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
-        $($self.$passes.$name $params;)*
+    ([$($pass:ident),*], $self: ident, $name: ident, $params:tt) => ({
+        $($self.$pass.$name $params;)*
     })
 }
 
@@ -95,28 +97,28 @@ macro_rules! expand_combined_late_lint_pass_methods {
 
 #[macro_export]
 macro_rules! declare_combined_late_lint_pass {
-    ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], [$hir:tt], $methods:tt) => (
+    ([$v:vis $name:ident, [$($pass:ident: $constructor:expr,)*]], $methods:tt) => (
         #[allow(non_snake_case)]
         $v struct $name {
-            $($passes: $passes,)*
+            $($pass: $pass,)*
         }
 
         impl $name {
             $v fn new() -> Self {
                 Self {
-                    $($passes: $constructor,)*
+                    $($pass: $constructor,)*
                 }
             }
 
             $v fn get_lints() -> LintArray {
                 let mut lints = Vec::new();
-                $(lints.extend_from_slice(&$passes::get_lints());)*
+                $(lints.extend_from_slice(&$pass::get_lints());)*
                 lints
             }
         }
 
         impl<'tcx> LateLintPass<'tcx> for $name {
-            expand_combined_late_lint_pass_methods!([$($passes),*], $methods);
+            expand_combined_late_lint_pass_methods!([$($pass),*], $methods);
         }
 
         #[allow(rustc::lint_pass_impl_without_macro)]
@@ -176,12 +178,14 @@ macro_rules! declare_early_lint_pass {
     )
 }
 
+// Declare the `EarlyLintPass` trait, which contains empty default definitions
+// for all the `check_*` methods.
 early_lint_methods!(declare_early_lint_pass, []);
 
 #[macro_export]
 macro_rules! expand_combined_early_lint_pass_method {
-    ([$($passes:ident),*], $self: ident, $name: ident, $params:tt) => ({
-        $($self.$passes.$name $params;)*
+    ([$($pass:ident),*], $self: ident, $name: ident, $params:tt) => ({
+        $($self.$pass.$name $params;)*
     })
 }
 
@@ -196,28 +200,28 @@ macro_rules! expand_combined_early_lint_pass_methods {
 
 #[macro_export]
 macro_rules! declare_combined_early_lint_pass {
-    ([$v:vis $name:ident, [$($passes:ident: $constructor:expr,)*]], $methods:tt) => (
+    ([$v:vis $name:ident, [$($pass:ident: $constructor:expr,)*]], $methods:tt) => (
         #[allow(non_snake_case)]
         $v struct $name {
-            $($passes: $passes,)*
+            $($pass: $pass,)*
         }
 
         impl $name {
             $v fn new() -> Self {
                 Self {
-                    $($passes: $constructor,)*
+                    $($pass: $constructor,)*
                 }
             }
 
             $v fn get_lints() -> LintArray {
                 let mut lints = Vec::new();
-                $(lints.extend_from_slice(&$passes::get_lints());)*
+                $(lints.extend_from_slice(&$pass::get_lints());)*
                 lints
             }
         }
 
         impl EarlyLintPass for $name {
-            expand_combined_early_lint_pass_methods!([$($passes),*], $methods);
+            expand_combined_early_lint_pass_methods!([$($pass),*], $methods);
         }
 
         #[allow(rustc::lint_pass_impl_without_macro)]
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index b5db94f8c06..dc352778f1d 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -617,7 +617,10 @@ trait UnusedDelimLint {
         lhs_needs_parens
             || (followed_by_block
                 && match &inner.kind {
-                    ExprKind::Ret(_) | ExprKind::Break(..) | ExprKind::Yield(..) => true,
+                    ExprKind::Ret(_)
+                    | ExprKind::Break(..)
+                    | ExprKind::Yield(..)
+                    | ExprKind::Yeet(..) => true,
                     ExprKind::Range(_lhs, Some(rhs), _limits) => {
                         matches!(rhs.kind, ExprKind::Block(..))
                     }
@@ -946,6 +949,7 @@ impl UnusedParens {
 }
 
 impl EarlyLintPass for UnusedParens {
+    #[inline]
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
         match e.kind {
             ExprKind::Let(ref pat, _, _) | ExprKind::ForLoop(ref pat, ..) => {
@@ -1164,6 +1168,7 @@ impl EarlyLintPass for UnusedBraces {
         <Self as UnusedDelimLint>::check_stmt(self, cx, s)
     }
 
+    #[inline]
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
         <Self as UnusedDelimLint>::check_expr(self, cx, e);
 
diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs
index 79f06ac146c..0b3c057345a 100644
--- a/compiler/rustc_llvm/build.rs
+++ b/compiler/rustc_llvm/build.rs
@@ -238,18 +238,20 @@ fn main() {
 
     if !is_crossed {
         cmd.arg("--system-libs");
-    } else if target.contains("windows-gnu") {
-        println!("cargo:rustc-link-lib=shell32");
-        println!("cargo:rustc-link-lib=uuid");
-    } else if target.contains("netbsd") || target.contains("haiku") || target.contains("darwin") {
-        println!("cargo:rustc-link-lib=z");
-    } else if target.starts_with("arm")
+    }
+
+    if (target.starts_with("arm") && !target.contains("freebsd"))
         || target.starts_with("mips-")
         || target.starts_with("mipsel-")
         || target.starts_with("powerpc-")
     {
         // 32-bit targets need to link libatomic.
         println!("cargo:rustc-link-lib=atomic");
+    } else if target.contains("windows-gnu") {
+        println!("cargo:rustc-link-lib=shell32");
+        println!("cargo:rustc-link-lib=uuid");
+    } else if target.contains("netbsd") || target.contains("haiku") || target.contains("darwin") {
+        println!("cargo:rustc-link-lib=z");
     }
     cmd.args(&components);
 
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 3a748f38995..5831d4693f1 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -1476,13 +1476,13 @@ extern "C" void LLVMRustFreeOperandBundleDef(OperandBundleDef *Bundle) {
 
 extern "C" LLVMValueRef LLVMRustBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
                                           LLVMValueRef *Args, unsigned NumArgs,
-                                          OperandBundleDef *Bundle) {
+                                          OperandBundleDef **OpBundles,
+                                          unsigned NumOpBundles) {
   Value *Callee = unwrap(Fn);
   FunctionType *FTy = unwrap<FunctionType>(Ty);
-  unsigned Len = Bundle ? 1 : 0;
-  ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
   return wrap(unwrap(B)->CreateCall(
-      FTy, Callee, makeArrayRef(unwrap(Args), NumArgs), Bundles));
+      FTy, Callee, makeArrayRef(unwrap(Args), NumArgs),
+      makeArrayRef(*OpBundles, NumOpBundles)));
 }
 
 extern "C" LLVMValueRef LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
@@ -1522,14 +1522,14 @@ extern "C" LLVMValueRef
 LLVMRustBuildInvoke(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn,
                     LLVMValueRef *Args, unsigned NumArgs,
                     LLVMBasicBlockRef Then, LLVMBasicBlockRef Catch,
-                    OperandBundleDef *Bundle, const char *Name) {
+                    OperandBundleDef **OpBundles, unsigned NumOpBundles,
+                    const char *Name) {
   Value *Callee = unwrap(Fn);
   FunctionType *FTy = unwrap<FunctionType>(Ty);
-  unsigned Len = Bundle ? 1 : 0;
-  ArrayRef<OperandBundleDef> Bundles = makeArrayRef(Bundle, Len);
   return wrap(unwrap(B)->CreateInvoke(FTy, Callee, unwrap(Then), unwrap(Catch),
                                       makeArrayRef(unwrap(Args), NumArgs),
-                                      Bundles, Name));
+                                      makeArrayRef(*OpBundles, NumOpBundles),
+                                      Name));
 }
 
 extern "C" void LLVMRustPositionBuilderAtStart(LLVMBuilderRef B,
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index 1a2389c7a84..01d7f3e03c5 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -13,7 +13,7 @@ use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_ast::{self as ast, *};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{Lrc, ReadGuard};
 use rustc_expand::base::SyntaxExtension;
 use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, LOCAL_CRATE};
 use rustc_hir::definitions::Definitions;
@@ -68,11 +68,12 @@ impl std::fmt::Debug for CStore {
 pub struct CrateLoader<'a> {
     // Immutable configuration.
     sess: &'a Session,
-    metadata_loader: Box<MetadataLoaderDyn>,
+    metadata_loader: &'a MetadataLoaderDyn,
+    definitions: ReadGuard<'a, Definitions>,
     local_crate_name: Symbol,
     // Mutable output.
-    cstore: CStore,
-    used_extern_options: FxHashSet<Symbol>,
+    cstore: &'a mut CStore,
+    used_extern_options: &'a mut FxHashSet<Symbol>,
 }
 
 pub enum LoadedMacro {
@@ -239,47 +240,49 @@ impl CStore {
             );
         }
     }
+
+    pub fn new(sess: &Session) -> CStore {
+        let mut stable_crate_ids = FxHashMap::default();
+        stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE);
+        CStore {
+            // We add an empty entry for LOCAL_CRATE (which maps to zero) in
+            // order to make array indices in `metas` match with the
+            // corresponding `CrateNum`. This first entry will always remain
+            // `None`.
+            metas: IndexVec::from_elem_n(None, 1),
+            injected_panic_runtime: None,
+            allocator_kind: None,
+            alloc_error_handler_kind: None,
+            has_global_allocator: false,
+            has_alloc_error_handler: false,
+            stable_crate_ids,
+            unused_externs: Vec::new(),
+        }
+    }
 }
 
 impl<'a> CrateLoader<'a> {
     pub fn new(
         sess: &'a Session,
-        metadata_loader: Box<MetadataLoaderDyn>,
-        local_crate_name: &str,
+        metadata_loader: &'a MetadataLoaderDyn,
+        local_crate_name: Symbol,
+        cstore: &'a mut CStore,
+        definitions: ReadGuard<'a, Definitions>,
+        used_extern_options: &'a mut FxHashSet<Symbol>,
     ) -> Self {
-        let mut stable_crate_ids = FxHashMap::default();
-        stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE);
-
         CrateLoader {
             sess,
             metadata_loader,
-            local_crate_name: Symbol::intern(local_crate_name),
-            cstore: CStore {
-                // We add an empty entry for LOCAL_CRATE (which maps to zero) in
-                // order to make array indices in `metas` match with the
-                // corresponding `CrateNum`. This first entry will always remain
-                // `None`.
-                metas: IndexVec::from_elem_n(None, 1),
-                injected_panic_runtime: None,
-                allocator_kind: None,
-                alloc_error_handler_kind: None,
-                has_global_allocator: false,
-                has_alloc_error_handler: false,
-                stable_crate_ids,
-                unused_externs: Vec::new(),
-            },
-            used_extern_options: Default::default(),
+            local_crate_name,
+            cstore,
+            used_extern_options,
+            definitions,
         }
     }
-
     pub fn cstore(&self) -> &CStore {
         &self.cstore
     }
 
-    pub fn into_cstore(self) -> CStore {
-        self.cstore
-    }
-
     fn existing_match(&self, name: Symbol, hash: Option<Svh>, kind: PathKind) -> Option<CrateNum> {
         for (cnum, data) in self.cstore.iter_crate_data() {
             if data.name() != name {
@@ -989,7 +992,6 @@ impl<'a> CrateLoader<'a> {
     pub fn process_extern_crate(
         &mut self,
         item: &ast::Item,
-        definitions: &Definitions,
         def_id: LocalDefId,
     ) -> Option<CrateNum> {
         match item.kind {
@@ -1000,7 +1002,7 @@ impl<'a> CrateLoader<'a> {
                 );
                 let name = match orig_name {
                     Some(orig_name) => {
-                        validate_crate_name(self.sess, orig_name.as_str(), Some(item.span));
+                        validate_crate_name(self.sess, orig_name, Some(item.span));
                         orig_name
                     }
                     None => item.ident.name,
@@ -1013,7 +1015,7 @@ impl<'a> CrateLoader<'a> {
 
                 let cnum = self.resolve_crate(name, item.span, dep_kind)?;
 
-                let path_len = definitions.def_path(def_id).data.len();
+                let path_len = self.definitions.def_path(def_id).data.len();
                 self.update_extern_crate(
                     cnum,
                     ExternCrate {
diff --git a/compiler/rustc_metadata/src/fs.rs b/compiler/rustc_metadata/src/fs.rs
index 4fa440c7ca6..7601f6bd322 100644
--- a/compiler/rustc_metadata/src/fs.rs
+++ b/compiler/rustc_metadata/src/fs.rs
@@ -61,8 +61,7 @@ pub fn encode_and_write_metadata(tcx: TyCtxt<'_>) -> (EncodedMetadata, bool) {
         .unwrap_or(MetadataKind::None);
 
     let crate_name = tcx.crate_name(LOCAL_CRATE);
-    let out_filename =
-        filename_for_metadata(tcx.sess, crate_name.as_str(), tcx.output_filenames(()));
+    let out_filename = filename_for_metadata(tcx.sess, crate_name, tcx.output_filenames(()));
     // To avoid races with another rustc process scanning the output directory,
     // we need to write the file somewhere else and atomically move it to its
     // final destination, with an `fs::rename` call. In order for the rename to
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 33cce0a411e..9d0ccfeb168 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -629,6 +629,9 @@ impl CrateStore for CStore {
     fn as_any(&self) -> &dyn Any {
         self
     }
+    fn untracked_as_any(&mut self) -> &mut dyn Any {
+        self
+    }
 
     fn crate_name(&self, cnum: CrateNum) -> Symbol {
         self.get_crate_data(cnum).root.name
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 1bd8f953508..0450abed51b 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -14,7 +14,7 @@ use rustc_index::vec::Idx;
 use rustc_middle::hir::nested_filter;
 use rustc_span::def_id::StableCrateId;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::Span;
 use rustc_target::spec::abi::Abi;
 
 #[inline]
@@ -1162,7 +1162,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
                 .filter_map(|(def_id, info)| {
                     let _ = info.as_owner()?;
                     let def_path_hash = definitions.def_path_hash(def_id);
-                    let span = resolutions.source_span.get(def_id).unwrap_or(&DUMMY_SP);
+                    let span = tcx.source_span(def_id);
                     debug_assert_eq!(span.parent(), None);
                     Some((def_path_hash, span))
                 })
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index 02fd03c0283..3f6e29ad611 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -141,8 +141,6 @@ pub fn provide(providers: &mut Providers) {
     providers.hir_attrs = |tcx, id| {
         tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs)
     };
-    providers.source_span =
-        |tcx, def_id| tcx.resolutions(()).source_span.get(def_id).copied().unwrap_or(DUMMY_SP);
     providers.def_span = |tcx, def_id| {
         let def_id = def_id.expect_local();
         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 7d2a6bda569..99e59c770d7 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -6,6 +6,7 @@
 use super::{BasicBlock, Constant, Field, Local, SwitchTargets, UserTypeProjection};
 
 use crate::mir::coverage::{CodeRegion, CoverageKind};
+use crate::traits::Reveal;
 use crate::ty::adjustment::PointerCast;
 use crate::ty::subst::SubstsRef;
 use crate::ty::{self, List, Ty};
@@ -100,6 +101,13 @@ impl MirPhase {
             MirPhase::Runtime(RuntimePhase::Optimized) => "runtime-optimized",
         }
     }
+
+    pub fn reveal(&self) -> Reveal {
+        match *self {
+            MirPhase::Built | MirPhase::Analysis(_) => Reveal::UserFacing,
+            MirPhase::Runtime(_) => Reveal::All,
+        }
+    }
 }
 
 /// See [`MirPhase::Analysis`].
@@ -400,7 +408,7 @@ impl std::fmt::Display for NonDivergingIntrinsic<'_> {
 #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, PartialEq, Eq, Hash, HashStable)]
 #[rustc_pass_by_value]
 pub enum RetagKind {
-    /// The initial retag when entering a function.
+    /// The initial retag of arguments when entering a function.
     FnEntry,
     /// Retag preparing for a two-phase borrow.
     TwoPhase,
@@ -518,12 +526,6 @@ pub enum TerminatorKind<'tcx> {
     SwitchInt {
         /// The discriminant value being tested.
         discr: Operand<'tcx>,
-
-        /// The type of value being tested.
-        /// This is always the same as the type of `discr`.
-        /// FIXME: remove this redundant information. Currently, it is relied on by pretty-printing.
-        switch_ty: Ty<'tcx>,
-
         targets: SwitchTargets,
     },
 
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 4ea333cff7d..013a1bccd3b 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -1,6 +1,3 @@
-use crate::mir;
-use crate::mir::interpret::Scalar;
-use crate::ty::{self, Ty, TyCtxt};
 use smallvec::{smallvec, SmallVec};
 
 use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind};
@@ -131,17 +128,8 @@ impl<'tcx> Terminator<'tcx> {
 }
 
 impl<'tcx> TerminatorKind<'tcx> {
-    pub fn if_(
-        tcx: TyCtxt<'tcx>,
-        cond: Operand<'tcx>,
-        t: BasicBlock,
-        f: BasicBlock,
-    ) -> TerminatorKind<'tcx> {
-        TerminatorKind::SwitchInt {
-            discr: cond,
-            switch_ty: tcx.types.bool,
-            targets: SwitchTargets::static_if(0, f, t),
-        }
+    pub fn if_(cond: Operand<'tcx>, t: BasicBlock, f: BasicBlock) -> TerminatorKind<'tcx> {
+        TerminatorKind::SwitchInt { discr: cond, targets: SwitchTargets::static_if(0, f, t) }
     }
 
     pub fn successors(&self) -> Successors<'_> {
@@ -264,11 +252,9 @@ impl<'tcx> TerminatorKind<'tcx> {
         }
     }
 
-    pub fn as_switch(&self) -> Option<(&Operand<'tcx>, Ty<'tcx>, &SwitchTargets)> {
+    pub fn as_switch(&self) -> Option<(&Operand<'tcx>, &SwitchTargets)> {
         match self {
-            TerminatorKind::SwitchInt { discr, switch_ty, targets } => {
-                Some((discr, *switch_ty, targets))
-            }
+            TerminatorKind::SwitchInt { discr, targets } => Some((discr, targets)),
             _ => None,
         }
     }
@@ -403,21 +389,12 @@ impl<'tcx> TerminatorKind<'tcx> {
         match *self {
             Return | Resume | Abort | Unreachable | GeneratorDrop => vec![],
             Goto { .. } => vec!["".into()],
-            SwitchInt { ref targets, switch_ty, .. } => ty::tls::with(|tcx| {
-                let param_env = ty::ParamEnv::empty();
-                let switch_ty = tcx.lift(switch_ty).unwrap();
-                let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size;
-                targets
-                    .values
-                    .iter()
-                    .map(|&u| {
-                        mir::ConstantKind::from_scalar(tcx, Scalar::from_uint(u, size), switch_ty)
-                            .to_string()
-                            .into()
-                    })
-                    .chain(iter::once("otherwise".into()))
-                    .collect()
-            }),
+            SwitchInt { ref targets, .. } => targets
+                .values
+                .iter()
+                .map(|&u| Cow::Owned(u.to_string()))
+                .chain(iter::once("otherwise".into()))
+                .collect(),
             Call { target: Some(_), cleanup: Some(_), .. } => {
                 vec!["return".into(), "unwind".into()]
             }
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index b21f50ae5ea..2ee3f551529 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -477,11 +477,9 @@ macro_rules! make_mir_visitor {
 
                     TerminatorKind::SwitchInt {
                         discr,
-                        switch_ty,
                         targets: _
                     } => {
                         self.visit_operand(discr, location);
-                        self.visit_ty($(& $mutability)? *switch_ty, TyContext::Location(location));
                     }
 
                     TerminatorKind::Drop {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index f2f2b22f52a..ab512804330 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -43,6 +43,8 @@ rustc_queries! {
     /// This span is meant for dep-tracking rather than diagnostics. It should not be used outside
     /// of rustc_middle::hir::source_map.
     query source_span(key: LocalDefId) -> Span {
+        // Accesses untracked data
+        eval_always
         desc { "getting the source span" }
     }
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index af573376a26..7d4971d1e9e 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -35,7 +35,7 @@ use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::steal::Steal;
-use rustc_data_structures::sync::{self, Lock, Lrc, ReadGuard, RwLock, WorkerLocal};
+use rustc_data_structures::sync::{self, Lock, Lrc, ReadGuard, WorkerLocal};
 use rustc_data_structures::unord::UnordSet;
 use rustc_data_structures::vec_map::VecMap;
 use rustc_errors::{
@@ -59,7 +59,7 @@ use rustc_query_system::dep_graph::DepNodeIndex;
 use rustc_query_system::ich::StableHashingContext;
 use rustc_serialize::opaque::{FileEncodeResult, FileEncoder};
 use rustc_session::config::{CrateType, OutputFilenames};
-use rustc_session::cstore::CrateStoreDyn;
+use rustc_session::cstore::{CrateStoreDyn, Untracked};
 use rustc_session::lint::Lint;
 use rustc_session::Limit;
 use rustc_session::Session;
@@ -182,20 +182,12 @@ impl<'tcx> CtxtInterners<'tcx> {
     /// Interns a type.
     #[allow(rustc::usage_of_ty_tykind)]
     #[inline(never)]
-    fn intern_ty(
-        &self,
-        kind: TyKind<'tcx>,
-        sess: &Session,
-        definitions: &rustc_hir::definitions::Definitions,
-        cstore: &CrateStoreDyn,
-        source_span: &IndexVec<LocalDefId, Span>,
-    ) -> Ty<'tcx> {
+    fn intern_ty(&self, kind: TyKind<'tcx>, sess: &Session, untracked: &Untracked) -> Ty<'tcx> {
         Ty(Interned::new_unchecked(
             self.type_
                 .intern(kind, |kind| {
                     let flags = super::flags::FlagComputation::for_kind(&kind);
-                    let stable_hash =
-                        self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind);
+                    let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
 
                     InternedInSet(self.arena.alloc(WithCachedTypeInfo {
                         internee: kind,
@@ -212,9 +204,7 @@ impl<'tcx> CtxtInterners<'tcx> {
         &self,
         flags: &ty::flags::FlagComputation,
         sess: &'a Session,
-        definitions: &'a rustc_hir::definitions::Definitions,
-        cstore: &'a CrateStoreDyn,
-        source_span: &'a IndexVec<LocalDefId, Span>,
+        untracked: &'a Untracked,
         val: &T,
     ) -> Fingerprint {
         // It's impossible to hash inference variables (and will ICE), so we don't need to try to cache them.
@@ -223,7 +213,7 @@ impl<'tcx> CtxtInterners<'tcx> {
             Fingerprint::ZERO
         } else {
             let mut hasher = StableHasher::new();
-            let mut hcx = StableHashingContext::new(sess, definitions, cstore, source_span);
+            let mut hcx = StableHashingContext::new(sess, untracked);
             val.hash_stable(&mut hcx, &mut hasher);
             hasher.finish()
         }
@@ -234,17 +224,14 @@ impl<'tcx> CtxtInterners<'tcx> {
         &self,
         kind: Binder<'tcx, PredicateKind<'tcx>>,
         sess: &Session,
-        definitions: &rustc_hir::definitions::Definitions,
-        cstore: &CrateStoreDyn,
-        source_span: &IndexVec<LocalDefId, Span>,
+        untracked: &Untracked,
     ) -> Predicate<'tcx> {
         Predicate(Interned::new_unchecked(
             self.predicate
                 .intern(kind, |kind| {
                     let flags = super::flags::FlagComputation::for_predicate(kind);
 
-                    let stable_hash =
-                        self.stable_hash(&flags, sess, definitions, cstore, source_span, &kind);
+                    let stable_hash = self.stable_hash(&flags, sess, untracked, &kind);
 
                     InternedInSet(self.arena.alloc(WithCachedTypeInfo {
                         internee: kind,
@@ -962,11 +949,9 @@ impl<'tcx> CommonTypes<'tcx> {
     fn new(
         interners: &CtxtInterners<'tcx>,
         sess: &Session,
-        definitions: &rustc_hir::definitions::Definitions,
-        cstore: &CrateStoreDyn,
-        source_span: &IndexVec<LocalDefId, Span>,
+        untracked: &Untracked,
     ) -> CommonTypes<'tcx> {
-        let mk = |ty| interners.intern_ty(ty, sess, definitions, cstore, source_span);
+        let mk = |ty| interners.intern_ty(ty, sess, untracked);
 
         CommonTypes {
             unit: mk(Tuple(List::empty())),
@@ -1112,8 +1097,7 @@ pub struct GlobalCtxt<'tcx> {
     /// Common consts, pre-interned for your convenience.
     pub consts: CommonConsts<'tcx>,
 
-    definitions: RwLock<Definitions>,
-
+    untracked: Untracked,
     /// Output of the resolver.
     pub(crate) untracked_resolutions: ty::ResolverGlobalCtxt,
     /// The entire crate as AST. This field serves as the input for the hir_crate query,
@@ -1278,28 +1262,21 @@ impl<'tcx> TyCtxt<'tcx> {
         lint_store: Lrc<dyn Any + sync::Send + sync::Sync>,
         arena: &'tcx WorkerLocal<Arena<'tcx>>,
         hir_arena: &'tcx WorkerLocal<hir::Arena<'tcx>>,
-        definitions: Definitions,
         untracked_resolutions: ty::ResolverGlobalCtxt,
+        untracked: Untracked,
         krate: Lrc<ast::Crate>,
         dep_graph: DepGraph,
         on_disk_cache: Option<&'tcx dyn OnDiskCache<'tcx>>,
         queries: &'tcx dyn query::QueryEngine<'tcx>,
         query_kinds: &'tcx [DepKindStruct<'tcx>],
-        crate_name: &str,
+        crate_name: Symbol,
         output_filenames: OutputFilenames,
     ) -> GlobalCtxt<'tcx> {
         let data_layout = s.target.parse_data_layout().unwrap_or_else(|err| {
             s.emit_fatal(err);
         });
         let interners = CtxtInterners::new(arena);
-        let common_types = CommonTypes::new(
-            &interners,
-            s,
-            &definitions,
-            &*untracked_resolutions.cstore,
-            // This is only used to create a stable hashing context.
-            &untracked_resolutions.source_span,
-        );
+        let common_types = CommonTypes::new(&interners, s, &untracked);
         let common_lifetimes = CommonLifetimes::new(&interners);
         let common_consts = CommonConsts::new(&interners, &common_types);
 
@@ -1310,11 +1287,11 @@ impl<'tcx> TyCtxt<'tcx> {
             hir_arena,
             interners,
             dep_graph,
-            definitions: RwLock::new(definitions),
             prof: s.prof.clone(),
             types: common_types,
             lifetimes: common_lifetimes,
             consts: common_consts,
+            untracked,
             untracked_resolutions,
             untracked_crate: Steal::new(krate),
             on_disk_cache,
@@ -1325,7 +1302,7 @@ impl<'tcx> TyCtxt<'tcx> {
             pred_rcache: Default::default(),
             selection_cache: Default::default(),
             evaluation_cache: Default::default(),
-            crate_name: Symbol::intern(crate_name),
+            crate_name,
             data_layout,
             alloc_map: Lock::new(interpret::AllocMap::new()),
             output_filenames: Arc::new(output_filenames),
@@ -1428,7 +1405,7 @@ impl<'tcx> TyCtxt<'tcx> {
         if let Some(id) = id.as_local() {
             self.definitions_untracked().def_key(id)
         } else {
-            self.untracked_resolutions.cstore.def_key(id)
+            self.untracked.cstore.def_key(id)
         }
     }
 
@@ -1442,7 +1419,7 @@ impl<'tcx> TyCtxt<'tcx> {
         if let Some(id) = id.as_local() {
             self.definitions_untracked().def_path(id)
         } else {
-            self.untracked_resolutions.cstore.def_path(id)
+            self.untracked.cstore.def_path(id)
         }
     }
 
@@ -1452,7 +1429,7 @@ impl<'tcx> TyCtxt<'tcx> {
         if let Some(def_id) = def_id.as_local() {
             self.definitions_untracked().def_path_hash(def_id)
         } else {
-            self.untracked_resolutions.cstore.def_path_hash(def_id)
+            self.untracked.cstore.def_path_hash(def_id)
         }
     }
 
@@ -1461,7 +1438,7 @@ impl<'tcx> TyCtxt<'tcx> {
         if crate_num == LOCAL_CRATE {
             self.sess.local_stable_crate_id()
         } else {
-            self.untracked_resolutions.cstore.stable_crate_id(crate_num)
+            self.untracked.cstore.stable_crate_id(crate_num)
         }
     }
 
@@ -1472,7 +1449,7 @@ impl<'tcx> TyCtxt<'tcx> {
         if stable_crate_id == self.sess.local_stable_crate_id() {
             LOCAL_CRATE
         } else {
-            self.untracked_resolutions.cstore.stable_crate_id_to_crate_num(stable_crate_id)
+            self.untracked.cstore.stable_crate_id_to_crate_num(stable_crate_id)
         }
     }
 
@@ -1487,11 +1464,11 @@ impl<'tcx> TyCtxt<'tcx> {
         // If this is a DefPathHash from the local crate, we can look up the
         // DefId in the tcx's `Definitions`.
         if stable_crate_id == self.sess.local_stable_crate_id() {
-            self.definitions.read().local_def_path_hash_to_def_id(hash, err).to_def_id()
+            self.untracked.definitions.read().local_def_path_hash_to_def_id(hash, err).to_def_id()
         } else {
             // If this is a DefPathHash from an upstream crate, let the CrateStore map
             // it to a DefId.
-            let cstore = &*self.untracked_resolutions.cstore;
+            let cstore = &*self.untracked.cstore;
             let cnum = cstore.stable_crate_id_to_crate_num(stable_crate_id);
             cstore.def_path_hash_to_def_id(cnum, hash)
         }
@@ -1505,7 +1482,7 @@ impl<'tcx> TyCtxt<'tcx> {
         let (crate_name, stable_crate_id) = if def_id.is_local() {
             (self.crate_name, self.sess.local_stable_crate_id())
         } else {
-            let cstore = &*self.untracked_resolutions.cstore;
+            let cstore = &*self.untracked.cstore;
             (cstore.crate_name(def_id.krate), cstore.stable_crate_id(def_id.krate))
         };
 
@@ -1547,7 +1524,7 @@ impl<'tcx> TyCtxtAt<'tcx> {
         // This is fine because:
         // - those queries are `eval_always` so we won't miss their result changing;
         // - this write will have happened before these queries are called.
-        let key = self.definitions.write().create_def(parent, data);
+        let key = self.untracked.definitions.write().create_def(parent, data);
 
         let feed = TyCtxtFeed { tcx: self.tcx, key };
         feed.def_span(self.span);
@@ -1561,7 +1538,7 @@ impl<'tcx> TyCtxt<'tcx> {
         // definitions change.
         self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE);
 
-        let definitions = &self.definitions;
+        let definitions = &self.untracked.definitions;
         std::iter::from_generator(|| {
             let mut i = 0;
 
@@ -1585,7 +1562,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
         // Leak a read lock once we start iterating on definitions, to prevent adding new ones
         // while iterating.  If some query needs to add definitions, it should be `ensure`d above.
-        let definitions = self.definitions.leak();
+        let definitions = self.untracked.definitions.leak();
         definitions.def_path_table()
     }
 
@@ -1597,28 +1574,28 @@ impl<'tcx> TyCtxt<'tcx> {
         self.ensure().hir_crate(());
         // Leak a read lock once we start iterating on definitions, to prevent adding new ones
         // while iterating.  If some query needs to add definitions, it should be `ensure`d above.
-        let definitions = self.definitions.leak();
+        let definitions = self.untracked.definitions.leak();
         definitions.def_path_hash_to_def_index_map()
     }
 
     /// Note that this is *untracked* and should only be used within the query
     /// system if the result is otherwise tracked through queries
     pub fn cstore_untracked(self) -> &'tcx CrateStoreDyn {
-        &*self.untracked_resolutions.cstore
+        &*self.untracked.cstore
     }
 
     /// Note that this is *untracked* and should only be used within the query
     /// system if the result is otherwise tracked through queries
     #[inline]
     pub fn definitions_untracked(self) -> ReadGuard<'tcx, Definitions> {
-        self.definitions.read()
+        self.untracked.definitions.read()
     }
 
     /// Note that this is *untracked* and should only be used within the query
     /// system if the result is otherwise tracked through queries
     #[inline]
     pub fn source_span_untracked(self, def_id: LocalDefId) -> Span {
-        self.untracked_resolutions.source_span.get(def_id).copied().unwrap_or(DUMMY_SP)
+        self.untracked.source_span.get(def_id).copied().unwrap_or(DUMMY_SP)
     }
 
     #[inline(always)]
@@ -1626,14 +1603,7 @@ impl<'tcx> TyCtxt<'tcx> {
         self,
         f: impl FnOnce(StableHashingContext<'_>) -> R,
     ) -> R {
-        let definitions = self.definitions_untracked();
-        let hcx = StableHashingContext::new(
-            self.sess,
-            &*definitions,
-            &*self.untracked_resolutions.cstore,
-            &self.untracked_resolutions.source_span,
-        );
-        f(hcx)
+        f(StableHashingContext::new(self.sess, &self.untracked))
     }
 
     pub fn serialize_query_result_cache(self, encoder: FileEncoder) -> FileEncodeResult {
@@ -2427,10 +2397,8 @@ impl<'tcx> TyCtxt<'tcx> {
         self.interners.intern_ty(
             st,
             self.sess,
-            &self.definitions.read(),
-            &*self.untracked_resolutions.cstore,
             // This is only used to create a stable hashing context.
-            &self.untracked_resolutions.source_span,
+            &self.untracked,
         )
     }
 
@@ -2439,10 +2407,8 @@ impl<'tcx> TyCtxt<'tcx> {
         self.interners.intern_predicate(
             binder,
             self.sess,
-            &self.definitions.read(),
-            &*self.untracked_resolutions.cstore,
             // This is only used to create a stable hashing context.
-            &self.untracked_resolutions.source_span,
+            &self.untracked,
         )
     }
 
@@ -3124,4 +3090,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
         // We want to check if the panic handler was defined in this crate
         tcx.lang_items().panic_impl().map_or(false, |did| did.is_local())
     };
+    providers.source_span =
+        |tcx, def_id| tcx.untracked.source_span.get(def_id).copied().unwrap_or(DUMMY_SP);
 }
diff --git a/compiler/rustc_middle/src/ty/error.rs b/compiler/rustc_middle/src/ty/error.rs
index d83e17574a0..aa61c39b8d8 100644
--- a/compiler/rustc_middle/src/ty/error.rs
+++ b/compiler/rustc_middle/src/ty/error.rs
@@ -986,23 +986,32 @@ fn foo(&self) -> Self::T { String::new() }
     }
 
     pub fn short_ty_string(self, ty: Ty<'tcx>) -> (String, Option<PathBuf>) {
-        let length_limit = 50;
-        let type_limit = 4;
+        let width = self.sess.diagnostic_width();
+        let length_limit = width.saturating_sub(30);
+        let mut type_limit = 50;
         let regular = FmtPrinter::new(self, hir::def::Namespace::TypeNS)
             .pretty_print_type(ty)
             .expect("could not write to `String`")
             .into_buffer();
-        if regular.len() <= length_limit {
+        if regular.len() <= width {
             return (regular, None);
         }
-        let short = FmtPrinter::new_with_limit(
-            self,
-            hir::def::Namespace::TypeNS,
-            rustc_session::Limit(type_limit),
-        )
-        .pretty_print_type(ty)
-        .expect("could not write to `String`")
-        .into_buffer();
+        let mut short;
+        loop {
+            // Look for the longest properly trimmed path that still fits in lenght_limit.
+            short = FmtPrinter::new_with_limit(
+                self,
+                hir::def::Namespace::TypeNS,
+                rustc_session::Limit(type_limit),
+            )
+            .pretty_print_type(ty)
+            .expect("could not write to `String`")
+            .into_buffer();
+            if short.len() <= length_limit || type_limit == 0 {
+                break;
+            }
+            type_limit -= 1;
+        }
         if regular == short {
             return (regular, None);
         }
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 48329da3e63..2e70ac256a7 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -234,6 +234,15 @@ impl<'tcx> Generics {
         }
     }
 
+    pub fn params_to(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx [GenericParamDef] {
+        if let Some(index) = param_index.checked_sub(self.parent_count) {
+            &self.params[..index]
+        } else {
+            tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
+                .params_to(param_index, tcx)
+        }
+    }
+
     /// Returns the `GenericParamDef` associated with this `EarlyBoundRegion`.
     pub fn region_param(
         &'tcx self,
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index c062e508ee3..659d99f025d 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -40,13 +40,12 @@ use rustc_data_structures::tagged_ptr::CopyTaggedPtr;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, LifetimeRes, Res};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalDefIdMap};
-use rustc_hir::definitions::Definitions;
 use rustc_hir::Node;
 use rustc_index::vec::IndexVec;
 use rustc_macros::HashStable;
 use rustc_query_system::ich::StableHashingContext;
 use rustc_serialize::{Decodable, Encodable};
-use rustc_session::cstore::CrateStoreDyn;
+use rustc_session::cstore::Untracked;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{ExpnId, Span};
@@ -150,21 +149,18 @@ mod sty;
 pub type RegisteredTools = FxHashSet<Ident>;
 
 pub struct ResolverOutputs {
-    pub definitions: Definitions,
     pub global_ctxt: ResolverGlobalCtxt,
     pub ast_lowering: ResolverAstLowering,
+    pub untracked: Untracked,
 }
 
 #[derive(Debug)]
 pub struct ResolverGlobalCtxt {
-    pub cstore: Box<CrateStoreDyn>,
     pub visibilities: FxHashMap<LocalDefId, Visibility>,
     /// This field is used to decide whether we should make `PRIVATE_IN_PUBLIC` a hard error.
     pub has_pub_restricted: bool,
     /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
     pub expn_that_defined: FxHashMap<LocalDefId, ExpnId>,
-    /// Reference span for definitions.
-    pub source_span: IndexVec<LocalDefId, Span>,
     pub effective_visibilities: EffectiveVisibilities,
     pub extern_crate_map: FxHashMap<LocalDefId, CrateNum>,
     pub maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index 47c1ce80756..9ea8dc6e69f 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -1,6 +1,7 @@
 //! Miscellaneous type-system utilities that are too small to deserve their own modules.
 
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
+use crate::mir;
 use crate::ty::layout::IntegerExt;
 use crate::ty::{
     self, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
@@ -15,6 +16,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_index::bit_set::GrowableBitSet;
+use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable;
 use rustc_span::{sym, DUMMY_SP};
 use rustc_target::abi::{Integer, IntegerType, Size, TargetDataLayout};
@@ -692,6 +694,80 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn bound_impl_subject(self, def_id: DefId) -> ty::EarlyBinder<ty::ImplSubject<'tcx>> {
         ty::EarlyBinder(self.impl_subject(def_id))
     }
+
+    /// Returns names of captured upvars for closures and generators.
+    ///
+    /// Here are some examples:
+    ///  - `name__field1__field2` when the upvar is captured by value.
+    ///  - `_ref__name__field` when the upvar is captured by reference.
+    ///
+    /// For generators this only contains upvars that are shared by all states.
+    pub fn closure_saved_names_of_captured_variables(
+        self,
+        def_id: DefId,
+    ) -> SmallVec<[String; 16]> {
+        let body = self.optimized_mir(def_id);
+
+        body.var_debug_info
+            .iter()
+            .filter_map(|var| {
+                let is_ref = match var.value {
+                    mir::VarDebugInfoContents::Place(place)
+                        if place.local == mir::Local::new(1) =>
+                    {
+                        // The projection is either `[.., Field, Deref]` or `[.., Field]`. It
+                        // implies whether the variable is captured by value or by reference.
+                        matches!(place.projection.last().unwrap(), mir::ProjectionElem::Deref)
+                    }
+                    _ => return None,
+                };
+                let prefix = if is_ref { "_ref__" } else { "" };
+                Some(prefix.to_owned() + var.name.as_str())
+            })
+            .collect()
+    }
+
+    // FIXME(eddyb) maybe precompute this? Right now it's computed once
+    // per generator monomorphization, but it doesn't depend on substs.
+    pub fn generator_layout_and_saved_local_names(
+        self,
+        def_id: DefId,
+    ) -> (
+        &'tcx ty::GeneratorLayout<'tcx>,
+        IndexVec<mir::GeneratorSavedLocal, Option<rustc_span::Symbol>>,
+    ) {
+        let tcx = self;
+        let body = tcx.optimized_mir(def_id);
+        let generator_layout = body.generator_layout().unwrap();
+        let mut generator_saved_local_names =
+            IndexVec::from_elem(None, &generator_layout.field_tys);
+
+        let state_arg = mir::Local::new(1);
+        for var in &body.var_debug_info {
+            let mir::VarDebugInfoContents::Place(place) = &var.value else { continue };
+            if place.local != state_arg {
+                continue;
+            }
+            match place.projection[..] {
+                [
+                    // Deref of the `Pin<&mut Self>` state argument.
+                    mir::ProjectionElem::Field(..),
+                    mir::ProjectionElem::Deref,
+                    // Field of a variant of the state.
+                    mir::ProjectionElem::Downcast(_, variant),
+                    mir::ProjectionElem::Field(field, _),
+                ] => {
+                    let name = &mut generator_saved_local_names
+                        [generator_layout.variant_fields[variant][field]];
+                    if name.is_none() {
+                        name.replace(var.name);
+                    }
+                }
+                _ => {}
+            }
+        }
+        (generator_layout, generator_saved_local_names)
+    }
 }
 
 struct OpaqueTypeExpander<'tcx> {
diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs
index 218a26e6279..38b1fa91d0a 100644
--- a/compiler/rustc_mir_build/src/build/expr/into.rs
+++ b/compiler/rustc_mir_build/src/build/expr/into.rs
@@ -183,7 +183,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     LogicalOp::And => (else_block, shortcircuit_block),
                     LogicalOp::Or => (shortcircuit_block, else_block),
                 };
-                let term = TerminatorKind::if_(this.tcx, lhs, blocks.0, blocks.1);
+                let term = TerminatorKind::if_(lhs, blocks.0, blocks.1);
                 this.cfg.terminate(block, source_info, term);
 
                 this.cfg.push_assign_constant(
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 691cbee2c73..e90db2c7d05 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -95,7 +95,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
                 let then_block = this.cfg.start_new_block();
                 let else_block = this.cfg.start_new_block();
-                let term = TerminatorKind::if_(this.tcx, operand, then_block, else_block);
+                let term = TerminatorKind::if_(operand, then_block, else_block);
 
                 let source_info = this.source_info(expr_span);
                 this.cfg.terminate(block, source_info, term);
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 58513bde2aa..6d5a98342d2 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -203,7 +203,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     self.source_info(match_start_span),
                     TerminatorKind::SwitchInt {
                         discr: Operand::Move(discr),
-                        switch_ty: discr_ty,
                         targets: switch_targets,
                     },
                 );
@@ -221,7 +220,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         0 => (second_bb, first_bb),
                         v => span_bug!(test.span, "expected boolean value but got {:?}", v),
                     };
-                    TerminatorKind::if_(self.tcx, Operand::Copy(place), true_bb, false_bb)
+                    TerminatorKind::if_(Operand::Copy(place), true_bb, false_bb)
                 } else {
                     // The switch may be inexhaustive so we have a catch all block
                     debug_assert_eq!(options.len() + 1, target_blocks.len());
@@ -232,7 +231,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     );
                     TerminatorKind::SwitchInt {
                         discr: Operand::Copy(place),
-                        switch_ty,
                         targets: switch_targets,
                     }
                 };
@@ -378,7 +376,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         self.cfg.terminate(
             block,
             source_info,
-            TerminatorKind::if_(self.tcx, Operand::Move(result), success_block, fail_block),
+            TerminatorKind::if_(Operand::Move(result), success_block, fail_block),
         );
     }
 
@@ -482,7 +480,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         self.cfg.terminate(
             eq_block,
             source_info,
-            TerminatorKind::if_(self.tcx, Operand::Move(eq_result), success_block, fail_block),
+            TerminatorKind::if_(Operand::Move(eq_result), success_block, fail_block),
         );
     }
 
diff --git a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
index ce87a1916b4..8610792c0eb 100644
--- a/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_dataflow/src/elaborate_drops.rs
@@ -596,7 +596,6 @@ where
                 source_info: self.source_info,
                 kind: TerminatorKind::SwitchInt {
                     discr: Operand::Move(discr),
-                    switch_ty: discr_ty,
                     targets: SwitchTargets::new(
                         values.iter().copied().zip(blocks.iter().copied()),
                         *blocks.last().unwrap(),
@@ -716,7 +715,7 @@ where
             is_cleanup: unwind.is_cleanup(),
             terminator: Some(Terminator {
                 source_info: self.source_info,
-                kind: TerminatorKind::if_(tcx, move_(can_go), succ, drop_block),
+                kind: TerminatorKind::if_(move_(can_go), succ, drop_block),
             }),
         };
         let loop_block = self.elaborator.patch().new_block(loop_block);
@@ -781,7 +780,6 @@ where
                 source_info: self.source_info,
                 kind: TerminatorKind::SwitchInt {
                     discr: move_(elem_size),
-                    switch_ty: tcx.types.usize,
                     targets: SwitchTargets::static_if(
                         0,
                         self.drop_loop_pair(ety, false, len),
@@ -1021,7 +1019,7 @@ where
             DropStyle::Static => on_set,
             DropStyle::Conditional | DropStyle::Open => {
                 let flag = self.elaborator.get_drop_flag(self.path).unwrap();
-                let term = TerminatorKind::if_(self.tcx(), flag, on_set, on_unset);
+                let term = TerminatorKind::if_(flag, on_set, on_unset);
                 self.new_block(unwind, term)
             }
         }
diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs
index 5c77f3ea395..5ff6b9e7e69 100644
--- a/compiler/rustc_mir_dataflow/src/framework/direction.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs
@@ -261,7 +261,7 @@ impl Direction for Backward {
                     propagate(pred, &tmp);
                 }
 
-                mir::TerminatorKind::SwitchInt { targets: _, ref discr, switch_ty: _ } => {
+                mir::TerminatorKind::SwitchInt { targets: _, ref discr } => {
                     let mut applier = BackwardSwitchIntEdgeEffectsApplier {
                         body,
                         pred,
@@ -577,7 +577,7 @@ impl Direction for Forward {
                 }
             }
 
-            SwitchInt { ref targets, ref discr, switch_ty: _ } => {
+            SwitchInt { ref targets, ref discr } => {
                 let mut applier = ForwardSwitchIntEdgeEffectsApplier {
                     exit_state,
                     targets,
diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs
index 036b5589849..3d22035f078 100644
--- a/compiler/rustc_mir_transform/src/add_retag.rs
+++ b/compiler/rustc_mir_transform/src/add_retag.rs
@@ -10,16 +10,6 @@ use rustc_middle::ty::{self, Ty, TyCtxt};
 
 pub struct AddRetag;
 
-/// Determines whether this place is "stable": Whether, if we evaluate it again
-/// after the assignment, we can be sure to obtain the same place value.
-/// (Concurrent accesses by other threads are no problem as these are anyway non-atomic
-/// copies.  Data races are UB.)
-fn is_stable(place: PlaceRef<'_>) -> bool {
-    // Which place this evaluates to can change with any memory write,
-    // so cannot assume deref to be stable.
-    !place.has_deref()
-}
-
 /// Determine whether this type may contain a reference (or box), and thus needs retagging.
 /// We will only recurse `depth` times into Tuples/ADTs to bound the cost of this.
 fn may_contain_reference<'tcx>(ty: Ty<'tcx>, depth: u32, tcx: TyCtxt<'tcx>) -> bool {
@@ -69,22 +59,10 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
         let basic_blocks = body.basic_blocks.as_mut();
         let local_decls = &body.local_decls;
         let needs_retag = |place: &Place<'tcx>| {
-            // FIXME: Instead of giving up for unstable places, we should introduce
-            // a temporary and retag on that.
-            is_stable(place.as_ref())
+            !place.has_deref() // we're not eally interested in stores to "outside" locations, they are hard to keep track of anyway
                 && may_contain_reference(place.ty(&*local_decls, tcx).ty, /*depth*/ 3, tcx)
                 && !local_decls[place.local].is_deref_temp()
         };
-        let place_base_raw = |place: &Place<'tcx>| {
-            // If this is a `Deref`, get the type of what we are deref'ing.
-            if place.has_deref() {
-                let ty = &local_decls[place.local].ty;
-                ty.is_unsafe_ptr()
-            } else {
-                // Not a deref, and thus not raw.
-                false
-            }
-        };
 
         // PART 1
         // Retag arguments at the beginning of the start block.
@@ -108,7 +86,7 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
         }
 
         // PART 2
-        // Retag return values of functions.  Also escape-to-raw the argument of `drop`.
+        // Retag return values of functions.
         // We collect the return destinations because we cannot mutate while iterating.
         let returns = basic_blocks
             .iter_mut()
@@ -140,30 +118,25 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
         }
 
         // PART 3
-        // Add retag after assignment.
+        // Add retag after assignments where data "enters" this function: the RHS is behind a deref and the LHS is not.
         for block_data in basic_blocks {
             // We want to insert statements as we iterate.  To this end, we
             // iterate backwards using indices.
             for i in (0..block_data.statements.len()).rev() {
                 let (retag_kind, place) = match block_data.statements[i].kind {
-                    // Retag-as-raw after escaping to a raw pointer, if the referent
-                    // is not already a raw pointer.
-                    StatementKind::Assign(box (lplace, Rvalue::AddressOf(_, ref rplace)))
-                        if !place_base_raw(rplace) =>
-                    {
-                        (RetagKind::Raw, lplace)
-                    }
                     // Retag after assignments of reference type.
                     StatementKind::Assign(box (ref place, ref rvalue)) if needs_retag(place) => {
-                        let kind = match rvalue {
-                            Rvalue::Ref(_, borrow_kind, _)
-                                if borrow_kind.allows_two_phase_borrow() =>
-                            {
-                                RetagKind::TwoPhase
-                            }
-                            _ => RetagKind::Default,
+                        let add_retag = match rvalue {
+                            // Ptr-creating operations already do their own internal retagging, no
+                            // need to also add a retag statement.
+                            Rvalue::Ref(..) | Rvalue::AddressOf(..) => false,
+                            _ => true,
                         };
-                        (kind, *place)
+                        if add_retag {
+                            (RetagKind::Default, *place)
+                        } else {
+                            continue;
+                        }
                     }
                     // Do nothing for the rest
                     _ => continue,
diff --git a/compiler/rustc_mir_transform/src/const_goto.rs b/compiler/rustc_mir_transform/src/const_goto.rs
index 0a305a40209..40eefda4f07 100644
--- a/compiler/rustc_mir_transform/src/const_goto.rs
+++ b/compiler/rustc_mir_transform/src/const_goto.rs
@@ -82,8 +82,9 @@ impl<'tcx> Visitor<'tcx> for ConstGotoOptimizationFinder<'_, 'tcx> {
                 }
 
                 let target_bb_terminator = target_bb.terminator();
-                let (discr, switch_ty, targets) = target_bb_terminator.kind.as_switch()?;
+                let (discr, targets) = target_bb_terminator.kind.as_switch()?;
                 if discr.place() == Some(*place) {
+                    let switch_ty = place.ty(self.body.local_decls(), self.tcx).ty;
                     // We now know that the Switch matches on the const place, and it is statementless
                     // Now find which value in the Switch matches the const value.
                     let const_value =
diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs
index 9c9ed5fa510..eba6a2b34e4 100644
--- a/compiler/rustc_mir_transform/src/coverage/tests.rs
+++ b/compiler/rustc_mir_transform/src/coverage/tests.rs
@@ -37,7 +37,7 @@ use rustc_data_structures::graph::WithSuccessors;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::mir::coverage::CoverageKind;
 use rustc_middle::mir::*;
-use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_middle::ty;
 use rustc_span::{self, BytePos, Pos, Span, DUMMY_SP};
 
 // All `TEMP_BLOCK` targets should be replaced before calling `to_body() -> mir::Body`.
@@ -47,7 +47,6 @@ struct MockBlocks<'tcx> {
     blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
     dummy_place: Place<'tcx>,
     next_local: usize,
-    bool_ty: Ty<'tcx>,
 }
 
 impl<'tcx> MockBlocks<'tcx> {
@@ -56,7 +55,6 @@ impl<'tcx> MockBlocks<'tcx> {
             blocks: IndexVec::new(),
             dummy_place: Place { local: RETURN_PLACE, projection: ty::List::empty() },
             next_local: 0,
-            bool_ty: TyCtxt::BOOL_TY_FOR_UNIT_TESTING,
         }
     }
 
@@ -157,7 +155,6 @@ impl<'tcx> MockBlocks<'tcx> {
     fn switchint(&mut self, some_from_block: Option<BasicBlock>) -> BasicBlock {
         let switchint_kind = TerminatorKind::SwitchInt {
             discr: Operand::Move(Place::from(self.new_temp())),
-            switch_ty: self.bool_ty, // just a dummy value
             targets: SwitchTargets::static_if(0, TEMP_BLOCK, TEMP_BLOCK),
         };
         self.add_block_from(some_from_block, switchint_kind)
diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
index 32e738bbcea..8a7b027ddda 100644
--- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
+++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs
@@ -121,7 +121,6 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
 
             let TerminatorKind::SwitchInt {
                 discr: parent_op,
-                switch_ty: parent_ty,
                 targets: parent_targets
             } = &bbs[parent].terminator().kind else {
                 unreachable!()
@@ -132,6 +131,7 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
                 Operand::Copy(x) => Operand::Copy(*x),
                 Operand::Constant(x) => Operand::Constant(x.clone()),
             };
+            let parent_ty = parent_op.ty(body.local_decls(), tcx);
             let statements_before = bbs[parent].statements.len();
             let parent_end = Location { block: parent, statement_index: statements_before };
 
@@ -153,7 +153,7 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
             // create temp to store inequality comparison between the two discriminants, `_t` in
             // example above
             let nequal = BinOp::Ne;
-            let comp_res_type = nequal.ty(tcx, *parent_ty, opt_data.child_ty);
+            let comp_res_type = nequal.ty(tcx, parent_ty, opt_data.child_ty);
             let comp_temp = patch.new_temp(comp_res_type, opt_data.child_source.span);
             patch.add_statement(parent_end, StatementKind::StorageLive(comp_temp));
 
@@ -181,7 +181,6 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
                 kind: TerminatorKind::SwitchInt {
                     // switch on the first discriminant, so we can mark the second one as dead
                     discr: parent_op,
-                    switch_ty: opt_data.child_ty,
                     targets: eq_targets,
                 },
             }));
@@ -193,12 +192,7 @@ impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
             let false_case = eq_bb;
             patch.patch_terminator(
                 parent,
-                TerminatorKind::if_(
-                    tcx,
-                    Operand::Move(Place::from(comp_temp)),
-                    true_case,
-                    false_case,
-                ),
+                TerminatorKind::if_(Operand::Move(Place::from(comp_temp)), true_case, false_case),
             );
 
             // generate StorageDead for the second_discriminant_temp not in use anymore
@@ -319,11 +313,11 @@ fn evaluate_candidate<'tcx>(
     let bbs = &body.basic_blocks;
     let TerminatorKind::SwitchInt {
         targets,
-        switch_ty: parent_ty,
-        ..
+        discr: parent_discr,
     } = &bbs[parent].terminator().kind else {
         return None
     };
+    let parent_ty = parent_discr.ty(body.local_decls(), tcx);
     let parent_dest = {
         let poss = targets.otherwise();
         // If the fallthrough on the parent is trivially unreachable, we can let the
@@ -339,12 +333,12 @@ fn evaluate_candidate<'tcx>(
     let (_, child) = targets.iter().next()?;
     let child_terminator = &bbs[child].terminator();
     let TerminatorKind::SwitchInt {
-        switch_ty: child_ty,
         targets: child_targets,
-        ..
+        discr: child_discr,
     } = &child_terminator.kind else {
         return None
     };
+    let child_ty = child_discr.ty(body.local_decls(), tcx);
     if child_ty != parent_ty {
         return None;
     }
@@ -372,7 +366,7 @@ fn evaluate_candidate<'tcx>(
     Some(OptimizationData {
         destination,
         child_place: *child_place,
-        child_ty: *child_ty,
+        child_ty,
         child_source: child_terminator.source_info,
     })
 }
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 8922298ecaf..c08593afe9d 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -877,11 +877,7 @@ fn insert_switch<'tcx>(
     let (assign, discr) = transform.get_discr(body);
     let switch_targets =
         SwitchTargets::new(cases.iter().map(|(i, bb)| ((*i) as u128, *bb)), default_block);
-    let switch = TerminatorKind::SwitchInt {
-        discr: Operand::Move(discr),
-        switch_ty: transform.discr_ty,
-        targets: switch_targets,
-    };
+    let switch = TerminatorKind::SwitchInt { discr: Operand::Move(discr), targets: switch_targets };
 
     let source_info = SourceInfo::outermost(body.span);
     body.basic_blocks_mut().raw.insert(
@@ -985,16 +981,6 @@ fn create_generator_drop_shim<'tcx>(
         tcx.mk_ptr(ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut }),
         source_info,
     );
-    if tcx.sess.opts.unstable_opts.mir_emit_retag {
-        // Alias tracking must know we changed the type
-        body.basic_blocks_mut()[START_BLOCK].statements.insert(
-            0,
-            Statement {
-                source_info,
-                kind: StatementKind::Retag(RetagKind::Raw, Box::new(Place::from(SELF_ARG))),
-            },
-        )
-    }
 
     // Make sure we remove dead blocks to remove
     // unrelated code from the resume part of the function
diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs
index a0ba69c89b0..ce05db5b762 100644
--- a/compiler/rustc_mir_transform/src/match_branches.rs
+++ b/compiler/rustc_mir_transform/src/match_branches.rs
@@ -55,10 +55,9 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
                 continue;
             }
 
-            let (discr, val, switch_ty, first, second) = match bbs[bb_idx].terminator().kind {
+            let (discr, val, first, second) = match bbs[bb_idx].terminator().kind {
                 TerminatorKind::SwitchInt {
                     discr: ref discr @ (Operand::Copy(_) | Operand::Move(_)),
-                    switch_ty,
                     ref targets,
                     ..
                 } if targets.iter().len() == 1 => {
@@ -66,7 +65,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
                     if target == targets.otherwise() {
                         continue;
                     }
-                    (discr, value, switch_ty, target, targets.otherwise())
+                    (discr, value, target, targets.otherwise())
                 }
                 // Only optimize switch int statements
                 _ => continue,
@@ -105,10 +104,11 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
             }
             // Take ownership of items now that we know we can optimize.
             let discr = discr.clone();
+            let discr_ty = discr.ty(&body.local_decls, tcx);
 
             // Introduce a temporary for the discriminant value.
             let source_info = bbs[bb_idx].terminator().source_info;
-            let discr_local = body.local_decls.push(LocalDecl::new(switch_ty, source_info.span));
+            let discr_local = body.local_decls.push(LocalDecl::new(discr_ty, source_info.span));
 
             // We already checked that first and second are different blocks,
             // and bb_idx has a different terminator from both of them.
@@ -130,10 +130,10 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
                             (*f).clone()
                         } else {
                             // Different value between blocks. Make value conditional on switch condition.
-                            let size = tcx.layout_of(param_env.and(switch_ty)).unwrap().size;
+                            let size = tcx.layout_of(param_env.and(discr_ty)).unwrap().size;
                             let const_cmp = Operand::const_from_scalar(
                                 tcx,
-                                switch_ty,
+                                discr_ty,
                                 rustc_const_eval::interpret::Scalar::from_uint(val, size),
                                 rustc_span::DUMMY_SP,
                             );
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index a115bb2831a..f92a0e826dc 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -177,16 +177,6 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
     if ty.is_some() {
         // The first argument (index 0), but add 1 for the return value.
         let dropee_ptr = Place::from(Local::new(1 + 0));
-        if tcx.sess.opts.unstable_opts.mir_emit_retag {
-            // Function arguments should be retagged, and we make this one raw.
-            body.basic_blocks_mut()[START_BLOCK].statements.insert(
-                0,
-                Statement {
-                    source_info,
-                    kind: StatementKind::Retag(RetagKind::Raw, Box::new(dropee_ptr)),
-                },
-            );
-        }
         let patch = {
             let param_env = tcx.param_env_reveal_all_normalized(def_id);
             let mut elaborator =
@@ -558,7 +548,6 @@ impl<'tcx> CloneShimBuilder<'tcx> {
                 statements.push(statement);
                 *kind = TerminatorKind::SwitchInt {
                     discr: Operand::Move(temp),
-                    switch_ty: discr_ty,
                     targets: SwitchTargets::new(cases.into_iter(), unreachable),
                 };
             }
diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs
index 405ebce4d22..8164b305278 100644
--- a/compiler/rustc_mir_transform/src/simplify_branches.rs
+++ b/compiler/rustc_mir_transform/src/simplify_branches.rs
@@ -24,12 +24,9 @@ impl<'tcx> MirPass<'tcx> for SimplifyConstCondition {
             let terminator = block.terminator_mut();
             terminator.kind = match terminator.kind {
                 TerminatorKind::SwitchInt {
-                    discr: Operand::Constant(ref c),
-                    switch_ty,
-                    ref targets,
-                    ..
+                    discr: Operand::Constant(ref c), ref targets, ..
                 } => {
-                    let constant = c.literal.try_eval_bits(tcx, param_env, switch_ty);
+                    let constant = c.literal.try_eval_bits(tcx, param_env, c.ty());
                     if let Some(constant) = constant {
                         let target = targets.target_for_value(constant);
                         TerminatorKind::Goto { target }
diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
index 321d8c63b6e..dcad1518eb6 100644
--- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
+++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
@@ -127,11 +127,8 @@ impl<'tcx> MirPass<'tcx> for SimplifyComparisonIntegral {
             let targets = SwitchTargets::new(iter::once((new_value, bb_cond)), bb_otherwise);
 
             let terminator = bb.terminator_mut();
-            terminator.kind = TerminatorKind::SwitchInt {
-                discr: Operand::Move(opt.to_switch_on),
-                switch_ty: opt.branch_value_ty,
-                targets,
-            };
+            terminator.kind =
+                TerminatorKind::SwitchInt { discr: Operand::Move(opt.to_switch_on), targets };
         }
 
         for (idx, bb_idx) in storage_deads_to_remove {
diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs
index 95fda2eafe8..06deca2fffb 100644
--- a/compiler/rustc_mir_transform/src/unreachable_prop.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs
@@ -76,7 +76,7 @@ where
     let terminator = match terminator_kind {
         // This will unconditionally run into an unreachable and is therefore unreachable as well.
         TerminatorKind::Goto { target } if is_unreachable(*target) => TerminatorKind::Unreachable,
-        TerminatorKind::SwitchInt { targets, discr, switch_ty } => {
+        TerminatorKind::SwitchInt { targets, discr } => {
             let otherwise = targets.otherwise();
 
             // If all targets are unreachable, we can be unreachable as well.
@@ -110,11 +110,7 @@ where
                     return None;
                 }
 
-                TerminatorKind::SwitchInt {
-                    discr: discr.clone(),
-                    switch_ty: *switch_ty,
-                    targets: new_targets,
-                }
+                TerminatorKind::SwitchInt { discr: discr.clone(), targets: new_targets }
             } else {
                 // If the otherwise branch is reachable, we don't want to delete any unreachable branches.
                 return None;
diff --git a/compiler/rustc_parse_format/Cargo.toml b/compiler/rustc_parse_format/Cargo.toml
index fcc68b3a219..72da398d3fc 100644
--- a/compiler/rustc_parse_format/Cargo.toml
+++ b/compiler/rustc_parse_format/Cargo.toml
@@ -5,3 +5,4 @@ edition = "2021"
 
 [dependencies]
 rustc_lexer = { path = "../rustc_lexer" }
+rustc_data_structures = { path = "../rustc_data_structures" }
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 0113eb4e3d1..9cbe04c1288 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -58,13 +58,13 @@ impl InnerOffset {
 
 /// A piece is a portion of the format string which represents the next part
 /// to emit. These are emitted as a stream by the `Parser` class.
-#[derive(Copy, Clone, Debug, PartialEq)]
+#[derive(Clone, Debug, PartialEq)]
 pub enum Piece<'a> {
     /// A literal string which should directly be emitted
     String(&'a str),
     /// This describes that formatting should process the next argument (as
     /// specified inside) for emission.
-    NextArgument(Argument<'a>),
+    NextArgument(Box<Argument<'a>>),
 }
 
 /// Representation of an argument specification.
@@ -244,7 +244,7 @@ impl<'a> Iterator for Parser<'a> {
                         } else {
                             self.suggest_positional_arg_instead_of_captured_arg(arg);
                         }
-                        Some(NextArgument(arg))
+                        Some(NextArgument(Box::new(arg)))
                     }
                 }
                 '}' => {
@@ -908,5 +908,9 @@ fn find_skips_from_snippet(
     (skips, true)
 }
 
+// Assert a reasonable size for `Piece`
+#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
+rustc_data_structures::static_assert_size!(Piece<'_>, 16);
+
 #[cfg(test)]
 mod tests;
diff --git a/compiler/rustc_parse_format/src/tests.rs b/compiler/rustc_parse_format/src/tests.rs
index 3f9cb149b53..2992ba845ab 100644
--- a/compiler/rustc_parse_format/src/tests.rs
+++ b/compiler/rustc_parse_format/src/tests.rs
@@ -76,51 +76,51 @@ fn invalid_precision() {
 fn format_nothing() {
     same(
         "{}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(0),
             position_span: InnerSpan { start: 2, end: 2 },
             format: fmtdflt(),
-        })],
+        }))],
     );
 }
 #[test]
 fn format_position() {
     same(
         "{3}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentIs(3),
             position_span: InnerSpan { start: 2, end: 3 },
             format: fmtdflt(),
-        })],
+        }))],
     );
 }
 #[test]
 fn format_position_nothing_else() {
     same(
         "{3:}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentIs(3),
             position_span: InnerSpan { start: 2, end: 3 },
             format: fmtdflt(),
-        })],
+        }))],
     );
 }
 #[test]
 fn format_named() {
     same(
         "{name}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentNamed("name"),
             position_span: InnerSpan { start: 2, end: 6 },
             format: fmtdflt(),
-        })],
+        }))],
     )
 }
 #[test]
 fn format_type() {
     same(
         "{3:x}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentIs(3),
             position_span: InnerSpan { start: 2, end: 3 },
             format: FormatSpec {
@@ -134,14 +134,14 @@ fn format_type() {
                 ty: "x",
                 ty_span: None,
             },
-        })],
+        }))],
     );
 }
 #[test]
 fn format_align_fill() {
     same(
         "{3:>}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentIs(3),
             position_span: InnerSpan { start: 2, end: 3 },
             format: FormatSpec {
@@ -155,11 +155,11 @@ fn format_align_fill() {
                 ty: "",
                 ty_span: None,
             },
-        })],
+        }))],
     );
     same(
         "{3:0<}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentIs(3),
             position_span: InnerSpan { start: 2, end: 3 },
             format: FormatSpec {
@@ -173,11 +173,11 @@ fn format_align_fill() {
                 ty: "",
                 ty_span: None,
             },
-        })],
+        }))],
     );
     same(
         "{3:*<abcd}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentIs(3),
             position_span: InnerSpan { start: 2, end: 3 },
             format: FormatSpec {
@@ -191,14 +191,14 @@ fn format_align_fill() {
                 ty: "abcd",
                 ty_span: Some(InnerSpan::new(6, 10)),
             },
-        })],
+        }))],
     );
 }
 #[test]
 fn format_counts() {
     same(
         "{:10x}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(0),
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
@@ -212,11 +212,11 @@ fn format_counts() {
                 ty: "x",
                 ty_span: None,
             },
-        })],
+        }))],
     );
     same(
         "{:10$.10x}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(0),
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
@@ -230,11 +230,11 @@ fn format_counts() {
                 ty: "x",
                 ty_span: None,
             },
-        })],
+        }))],
     );
     same(
         "{1:0$.10x}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentIs(1),
             position_span: InnerSpan { start: 2, end: 3 },
             format: FormatSpec {
@@ -248,11 +248,11 @@ fn format_counts() {
                 ty: "x",
                 ty_span: None,
             },
-        })],
+        }))],
     );
     same(
         "{:.*x}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(1),
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
@@ -266,11 +266,11 @@ fn format_counts() {
                 ty: "x",
                 ty_span: None,
             },
-        })],
+        }))],
     );
     same(
         "{:.10$x}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(0),
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
@@ -284,11 +284,11 @@ fn format_counts() {
                 ty: "x",
                 ty_span: None,
             },
-        })],
+        }))],
     );
     same(
         "{:a$.b$?}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(0),
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
@@ -302,11 +302,11 @@ fn format_counts() {
                 ty: "?",
                 ty_span: None,
             },
-        })],
+        }))],
     );
     same(
         "{:.4}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(0),
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
@@ -320,14 +320,14 @@ fn format_counts() {
                 ty: "",
                 ty_span: None,
             },
-        })],
+        }))],
     )
 }
 #[test]
 fn format_flags() {
     same(
         "{:-}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(0),
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
@@ -341,11 +341,11 @@ fn format_flags() {
                 ty: "",
                 ty_span: None,
             },
-        })],
+        }))],
     );
     same(
         "{:+#}",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(0),
             position_span: InnerSpan { start: 2, end: 2 },
             format: FormatSpec {
@@ -359,7 +359,7 @@ fn format_flags() {
                 ty: "",
                 ty_span: None,
             },
-        })],
+        }))],
     );
 }
 #[test]
@@ -368,7 +368,7 @@ fn format_mixture() {
         "abcd {3:x} efg",
         &[
             String("abcd "),
-            NextArgument(Argument {
+            NextArgument(Box::new(Argument {
                 position: ArgumentIs(3),
                 position_span: InnerSpan { start: 7, end: 8 },
                 format: FormatSpec {
@@ -382,7 +382,7 @@ fn format_mixture() {
                     ty: "x",
                     ty_span: None,
                 },
-            }),
+            })),
             String(" efg"),
         ],
     );
@@ -391,18 +391,18 @@ fn format_mixture() {
 fn format_whitespace() {
     same(
         "{ }",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(0),
             position_span: InnerSpan { start: 2, end: 3 },
             format: fmtdflt(),
-        })],
+        }))],
     );
     same(
         "{  }",
-        &[NextArgument(Argument {
+        &[NextArgument(Box::new(Argument {
             position: ArgumentImplicitlyIs(0),
             position_span: InnerSpan { start: 2, end: 4 },
             format: fmtdflt(),
-        })],
+        }))],
     );
 }
diff --git a/compiler/rustc_query_system/src/ich/hcx.rs b/compiler/rustc_query_system/src/ich/hcx.rs
index 6378ec10875..163da59edd5 100644
--- a/compiler/rustc_query_system/src/ich/hcx.rs
+++ b/compiler/rustc_query_system/src/ich/hcx.rs
@@ -6,9 +6,8 @@ use rustc_data_structures::stable_hasher::{HashStable, HashingControls, StableHa
 use rustc_data_structures::sync::Lrc;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::definitions::{DefPathHash, Definitions};
-use rustc_index::vec::IndexVec;
-use rustc_session::cstore::CrateStore;
+use rustc_hir::definitions::DefPathHash;
+use rustc_session::cstore::Untracked;
 use rustc_session::Session;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::Symbol;
@@ -20,9 +19,7 @@ use rustc_span::{BytePos, CachingSourceMapView, SourceFile, Span, SpanData, DUMM
 /// things (e.g., each `DefId`/`DefPath` is only hashed once).
 #[derive(Clone)]
 pub struct StableHashingContext<'a> {
-    definitions: &'a Definitions,
-    cstore: &'a dyn CrateStore,
-    source_span: &'a IndexVec<LocalDefId, Span>,
+    untracked: &'a Untracked,
     // The value of `-Z incremental-ignore-spans`.
     // This field should only be used by `unstable_opts_incremental_ignore_span`
     incremental_ignore_spans: bool,
@@ -49,19 +46,12 @@ pub(super) enum BodyResolver<'tcx> {
 
 impl<'a> StableHashingContext<'a> {
     #[inline]
-    pub fn new(
-        sess: &'a Session,
-        definitions: &'a Definitions,
-        cstore: &'a dyn CrateStore,
-        source_span: &'a IndexVec<LocalDefId, Span>,
-    ) -> Self {
+    pub fn new(sess: &'a Session, untracked: &'a Untracked) -> Self {
         let hash_spans_initial = !sess.opts.unstable_opts.incremental_ignore_spans;
 
         StableHashingContext {
             body_resolver: BodyResolver::Forbidden,
-            definitions,
-            cstore,
-            source_span,
+            untracked,
             incremental_ignore_spans: sess.opts.unstable_opts.incremental_ignore_spans,
             caching_source_map: None,
             raw_source_map: sess.source_map(),
@@ -100,13 +90,13 @@ impl<'a> StableHashingContext<'a> {
         if let Some(def_id) = def_id.as_local() {
             self.local_def_path_hash(def_id)
         } else {
-            self.cstore.def_path_hash(def_id)
+            self.untracked.cstore.def_path_hash(def_id)
         }
     }
 
     #[inline]
     pub fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash {
-        self.definitions.def_path_hash(def_id)
+        self.untracked.definitions.read().def_path_hash(def_id)
     }
 
     #[inline]
@@ -156,7 +146,7 @@ impl<'a> rustc_span::HashStableContext for StableHashingContext<'a> {
 
     #[inline]
     fn def_span(&self, def_id: LocalDefId) -> Span {
-        *self.source_span.get(def_id).unwrap_or(&DUMMY_SP)
+        *self.untracked.source_span.get(def_id).unwrap_or(&DUMMY_SP)
     }
 
     #[inline]
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 9c90d67aadf..f4a6a08df1c 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -836,12 +836,11 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
         } else if orig_name == Some(kw::SelfLower) {
             Some(self.r.graph_root)
         } else {
-            self.r.crate_loader.process_extern_crate(item, &self.r.definitions, local_def_id).map(
-                |crate_id| {
-                    self.r.extern_crate_map.insert(local_def_id, crate_id);
-                    self.r.expect_module(crate_id.as_def_id())
-                },
-            )
+            let crate_id = self.r.crate_loader().process_extern_crate(item, local_def_id);
+            crate_id.map(|crate_id| {
+                self.r.extern_crate_map.insert(local_def_id, crate_id);
+                self.r.expect_module(crate_id.as_def_id())
+            })
         }
         .map(|module| {
             let used = self.process_macro_use_imports(item, module);
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index f6b6cf3a94c..37771693417 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -153,7 +153,7 @@ impl<'a> Resolver<'a> {
             if !candidates.is_empty() {
                 show_candidates(
                     &self.session,
-                    &self.source_span,
+                    &self.untracked.source_span,
                     &mut err,
                     span,
                     &candidates,
@@ -682,7 +682,7 @@ impl<'a> Resolver<'a> {
                     }
                     show_candidates(
                         &self.session,
-                        &self.source_span,
+                        &self.untracked.source_span,
                         &mut err,
                         Some(span),
                         &import_suggestions,
@@ -1298,7 +1298,8 @@ impl<'a> Resolver<'a> {
                     // otherwise cause duplicate suggestions.
                     continue;
                 }
-                if let Some(crate_id) = self.crate_loader.maybe_process_path_extern(ident.name) {
+                let crate_id = self.crate_loader().maybe_process_path_extern(ident.name);
+                if let Some(crate_id) = crate_id {
                     let crate_root = self.expect_module(crate_id.as_def_id());
                     suggestions.extend(self.lookup_import_candidates_from_module(
                         lookup_ident,
@@ -1335,7 +1336,7 @@ impl<'a> Resolver<'a> {
             self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected);
         show_candidates(
             &self.session,
-            &self.source_span,
+            &self.untracked.source_span,
             err,
             None,
             &import_suggestions,
diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs
index 85399385d1f..b8efa3f8b27 100644
--- a/compiler/rustc_resolve/src/effective_visibilities.rs
+++ b/compiler/rustc_resolve/src/effective_visibilities.rs
@@ -107,7 +107,7 @@ impl<'r, 'a> EffectiveVisibilitiesVisitor<'r, 'a> {
                 r.effective_visibilities.update_eff_vis(
                     r.local_def_id(node_id),
                     eff_vis,
-                    ResolverTree(&r.definitions, &r.crate_loader),
+                    ResolverTree(&r.untracked),
                 )
             }
         }
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index b100a8c17cf..4d896b05526 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -541,7 +541,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
             if let Some(candidate) = &err.candidate {
                 import_candidates(
                     self.r.session,
-                    &self.r.source_span,
+                    &self.r.untracked.source_span,
                     &mut diag,
                     Some(err.span),
                     &candidate,
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index df59a350ea7..d43983ea815 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1663,8 +1663,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                         if !module.no_implicit_prelude {
                             let extern_prelude = self.r.extern_prelude.clone();
                             names.extend(extern_prelude.iter().flat_map(|(ident, _)| {
-                                self.r.crate_loader.maybe_process_path_extern(ident.name).and_then(
-                                    |crate_id| {
+                                self.r
+                                    .crate_loader()
+                                    .maybe_process_path_extern(ident.name)
+                                    .and_then(|crate_id| {
                                         let crate_mod =
                                             Res::Def(DefKind::Mod, crate_id.as_def_id());
 
@@ -1673,8 +1675,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                                         } else {
                                             None
                                         }
-                                    },
-                                )
+                                    })
                             }));
 
                             if let Some(prelude) = self.r.prelude {
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 4ef89cfb255..24e4b5bdd3f 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -29,7 +29,7 @@ use rustc_ast::{self as ast, NodeId, CRATE_NODE_ID};
 use rustc_ast::{AngleBracketedArg, Crate, Expr, ExprKind, GenericArg, GenericArgs, LitKind, Path};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::intern::Interned;
-use rustc_data_structures::sync::Lrc;
+use rustc_data_structures::sync::{Lrc, RwLock};
 use rustc_errors::{Applicability, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind};
 use rustc_hir::def::Namespace::*;
@@ -46,7 +46,7 @@ use rustc_middle::span_bug;
 use rustc_middle::ty::{self, DefIdTree, MainDefinition, RegisteredTools};
 use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs};
 use rustc_query_system::ich::StableHashingContext;
-use rustc_session::cstore::{CrateStore, MetadataLoaderDyn};
+use rustc_session::cstore::{CrateStore, MetadataLoaderDyn, Untracked};
 use rustc_session::lint::LintBuffer;
 use rustc_session::Session;
 use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency};
@@ -866,11 +866,8 @@ struct MacroData {
 pub struct Resolver<'a> {
     session: &'a Session,
 
-    definitions: Definitions,
     /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
     expn_that_defined: FxHashMap<LocalDefId, ExpnId>,
-    /// Reference span for definitions.
-    source_span: IndexVec<LocalDefId, Span>,
 
     graph_root: Module<'a>,
 
@@ -954,7 +951,10 @@ pub struct Resolver<'a> {
     arenas: &'a ResolverArenas<'a>,
     dummy_binding: &'a NameBinding<'a>,
 
-    crate_loader: CrateLoader<'a>,
+    local_crate_name: Symbol,
+    metadata_loader: Box<MetadataLoaderDyn>,
+    untracked: Untracked,
+    used_extern_options: FxHashSet<Symbol>,
     macro_names: FxHashSet<Ident>,
     builtin_macros: FxHashMap<Symbol, BuiltinMacroState>,
     /// A small map keeping true kinds of built-in macros that appear to be fn-like on
@@ -1112,15 +1112,15 @@ impl<'a> AsMut<Resolver<'a>> for Resolver<'a> {
 /// A minimal subset of resolver that can implemenent `DefIdTree`, sometimes
 /// required to satisfy borrow checker by avoiding borrowing the whole resolver.
 #[derive(Clone, Copy)]
-struct ResolverTree<'a, 'b>(&'a Definitions, &'a CrateLoader<'b>);
+struct ResolverTree<'a>(&'a Untracked);
 
-impl DefIdTree for ResolverTree<'_, '_> {
+impl DefIdTree for ResolverTree<'_> {
     #[inline]
     fn opt_parent(self, id: DefId) -> Option<DefId> {
-        let ResolverTree(definitions, crate_loader) = self;
+        let ResolverTree(Untracked { definitions, cstore, .. }) = self;
         match id.as_local() {
-            Some(id) => definitions.def_key(id).parent,
-            None => crate_loader.cstore().def_key(id).parent,
+            Some(id) => definitions.read().def_key(id).parent,
+            None => cstore.as_any().downcast_ref::<CStore>().unwrap().def_key(id).parent,
         }
         .map(|index| DefId { index, ..id })
     }
@@ -1129,7 +1129,7 @@ impl DefIdTree for ResolverTree<'_, '_> {
 impl<'a, 'b> DefIdTree for &'a Resolver<'b> {
     #[inline]
     fn opt_parent(self, id: DefId) -> Option<DefId> {
-        ResolverTree(&self.definitions, &self.crate_loader).opt_parent(id)
+        ResolverTree(&self.untracked).opt_parent(id)
     }
 }
 
@@ -1156,10 +1156,10 @@ impl Resolver<'_> {
             "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
             node_id,
             data,
-            self.definitions.def_key(self.node_id_to_def_id[&node_id]),
+            self.untracked.definitions.read().def_key(self.node_id_to_def_id[&node_id]),
         );
 
-        let def_id = self.definitions.create_def(parent, data);
+        let def_id = self.untracked.definitions.write().create_def(parent, data);
 
         // Create the definition.
         if expn_id != ExpnId::root() {
@@ -1168,7 +1168,7 @@ impl Resolver<'_> {
 
         // A relative span's parent must be an absolute span.
         debug_assert_eq!(span.data_untracked().parent, None);
-        let _id = self.source_span.push(span);
+        let _id = self.untracked.source_span.push(span);
         debug_assert_eq!(_id, def_id);
 
         // Some things for which we allocate `LocalDefId`s don't correspond to
@@ -1196,7 +1196,7 @@ impl<'a> Resolver<'a> {
     pub fn new(
         session: &'a Session,
         krate: &Crate,
-        crate_name: &str,
+        crate_name: Symbol,
         metadata_loader: Box<MetadataLoaderDyn>,
         arenas: &'a ResolverArenas<'a>,
     ) -> Resolver<'a> {
@@ -1258,9 +1258,7 @@ impl<'a> Resolver<'a> {
         let mut resolver = Resolver {
             session,
 
-            definitions,
             expn_that_defined: Default::default(),
-            source_span,
 
             // The outermost module has def ID 0; this is not reflected in the
             // AST.
@@ -1311,7 +1309,14 @@ impl<'a> Resolver<'a> {
                 vis: ty::Visibility::Public,
             }),
 
-            crate_loader: CrateLoader::new(session, metadata_loader, crate_name),
+            metadata_loader,
+            local_crate_name: crate_name,
+            used_extern_options: Default::default(),
+            untracked: Untracked {
+                cstore: Box::new(CStore::new(session)),
+                source_span,
+                definitions: RwLock::new(definitions),
+            },
             macro_names: FxHashSet::default(),
             builtin_macros: Default::default(),
             builtin_macro_kinds: Default::default(),
@@ -1402,9 +1407,6 @@ impl<'a> Resolver<'a> {
 
     pub fn into_outputs(self) -> ResolverOutputs {
         let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect();
-        let definitions = self.definitions;
-        let cstore = Box::new(self.crate_loader.into_cstore());
-        let source_span = self.source_span;
         let expn_that_defined = self.expn_that_defined;
         let visibilities = self.visibilities;
         let has_pub_restricted = self.has_pub_restricted;
@@ -1416,9 +1418,8 @@ impl<'a> Resolver<'a> {
         let main_def = self.main_def;
         let confused_type_with_std_module = self.confused_type_with_std_module;
         let effective_visibilities = self.effective_visibilities;
+        let untracked = self.untracked;
         let global_ctxt = ResolverGlobalCtxt {
-            cstore,
-            source_span,
             expn_that_defined,
             visibilities,
             has_pub_restricted,
@@ -1453,16 +1454,16 @@ impl<'a> Resolver<'a> {
             builtin_macro_kinds: self.builtin_macro_kinds,
             lifetime_elision_allowed: self.lifetime_elision_allowed,
         };
-        ResolverOutputs { definitions, global_ctxt, ast_lowering }
+        ResolverOutputs { global_ctxt, ast_lowering, untracked }
     }
 
     pub fn clone_outputs(&self) -> ResolverOutputs {
         let proc_macros = self.proc_macros.iter().map(|id| self.local_def_id(*id)).collect();
-        let definitions = self.definitions.clone();
+        let definitions = self.untracked.definitions.clone();
         let cstore = Box::new(self.cstore().clone());
+        let untracked =
+            Untracked { cstore, source_span: self.untracked.source_span.clone(), definitions };
         let global_ctxt = ResolverGlobalCtxt {
-            cstore,
-            source_span: self.source_span.clone(),
             expn_that_defined: self.expn_that_defined.clone(),
             visibilities: self.visibilities.clone(),
             has_pub_restricted: self.has_pub_restricted,
@@ -1497,20 +1498,26 @@ impl<'a> Resolver<'a> {
             builtin_macro_kinds: self.builtin_macro_kinds.clone(),
             lifetime_elision_allowed: self.lifetime_elision_allowed.clone(),
         };
-        ResolverOutputs { definitions, global_ctxt, ast_lowering }
+        ResolverOutputs { global_ctxt, ast_lowering, untracked }
     }
 
     fn create_stable_hashing_context(&self) -> StableHashingContext<'_> {
-        StableHashingContext::new(
-            self.session,
-            &self.definitions,
-            self.crate_loader.cstore(),
-            &self.source_span,
+        StableHashingContext::new(self.session, &self.untracked)
+    }
+
+    pub fn crate_loader(&mut self) -> CrateLoader<'_> {
+        CrateLoader::new(
+            &self.session,
+            &*self.metadata_loader,
+            self.local_crate_name,
+            &mut *self.untracked.cstore.untracked_as_any().downcast_mut().unwrap(),
+            self.untracked.definitions.read(),
+            &mut self.used_extern_options,
         )
     }
 
     pub fn cstore(&self) -> &CStore {
-        self.crate_loader.cstore()
+        self.untracked.cstore.as_any().downcast_ref().unwrap()
     }
 
     fn dummy_ext(&self, macro_kind: MacroKind) -> Lrc<SyntaxExtension> {
@@ -1553,7 +1560,7 @@ impl<'a> Resolver<'a> {
             self.session.time("resolve_main", || self.resolve_main());
             self.session.time("resolve_check_unused", || self.check_unused(krate));
             self.session.time("resolve_report_errors", || self.report_errors(krate));
-            self.session.time("resolve_postprocess", || self.crate_loader.postprocess(krate));
+            self.session.time("resolve_postprocess", || self.crate_loader().postprocess(krate));
         });
     }
 
@@ -1871,10 +1878,10 @@ impl<'a> Resolver<'a> {
             } else {
                 let crate_id = if finalize {
                     let Some(crate_id) =
-                        self.crate_loader.process_path_extern(ident.name, ident.span) else { return Some(self.dummy_binding); };
+                        self.crate_loader().process_path_extern(ident.name, ident.span) else { return Some(self.dummy_binding); };
                     crate_id
                 } else {
-                    self.crate_loader.maybe_process_path_extern(ident.name)?
+                    self.crate_loader().maybe_process_path_extern(ident.name)?
                 };
                 let crate_root = self.expect_module(crate_id.as_def_id());
                 let vis = ty::Visibility::<LocalDefId>::Public;
@@ -1946,14 +1953,14 @@ impl<'a> Resolver<'a> {
     /// Retrieves the span of the given `DefId` if `DefId` is in the local crate.
     #[inline]
     pub fn opt_span(&self, def_id: DefId) -> Option<Span> {
-        def_id.as_local().map(|def_id| self.source_span[def_id])
+        def_id.as_local().map(|def_id| self.untracked.source_span[def_id])
     }
 
     /// Retrieves the name of the given `DefId`.
     #[inline]
     pub fn opt_name(&self, def_id: DefId) -> Option<Symbol> {
         let def_key = match def_id.as_local() {
-            Some(def_id) => self.definitions.def_key(def_id),
+            Some(def_id) => self.untracked.definitions.read().def_key(def_id),
             None => self.cstore().def_key(def_id),
         };
         def_key.get_opt_name()
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 8c7972f8eeb..b5b1602c5e0 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -455,7 +455,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
     }
 
     fn get_proc_macro_quoted_span(&self, krate: CrateNum, id: usize) -> Span {
-        self.crate_loader.cstore().get_proc_macro_quoted_span_untracked(krate, id, self.session)
+        self.cstore().get_proc_macro_quoted_span_untracked(krate, id, self.session)
     }
 
     fn declare_proc_macro(&mut self, id: NodeId) {
diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs
index b4528853825..9ae07cb005b 100644
--- a/compiler/rustc_save_analysis/src/dump_visitor.rs
+++ b/compiler/rustc_save_analysis/src/dump_visitor.rs
@@ -111,7 +111,7 @@ impl<'tcx> DumpVisitor<'tcx> {
         self.save_ctxt.lookup_def_id(ref_id)
     }
 
-    pub fn dump_crate_info(&mut self, name: &str) {
+    pub fn dump_crate_info(&mut self, name: Symbol) {
         let source_file = self.tcx.sess.local_crate_source_file.as_ref();
         let crate_root = source_file.map(|source_file| {
             let source_file = Path::new(source_file);
@@ -124,7 +124,7 @@ impl<'tcx> DumpVisitor<'tcx> {
 
         let data = CratePreludeData {
             crate_id: GlobalCrateId {
-                name: name.into(),
+                name: name.to_string(),
                 disambiguator: (self.tcx.sess.local_stable_crate_id().to_u64(), 0),
             },
             crate_root: crate_root.unwrap_or_else(|| "<no source>".to_owned()),
@@ -135,7 +135,7 @@ impl<'tcx> DumpVisitor<'tcx> {
         self.dumper.crate_prelude(data);
     }
 
-    pub fn dump_compilation_options(&mut self, input: &Input, crate_name: &str) {
+    pub fn dump_compilation_options(&mut self, input: &Input, crate_name: Symbol) {
         // Apply possible `remap-path-prefix` remapping to the input source file
         // (and don't include remapping args anymore)
         let (program, arguments) = {
diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs
index f05eb2b7432..7735c571310 100644
--- a/compiler/rustc_save_analysis/src/lib.rs
+++ b/compiler/rustc_save_analysis/src/lib.rs
@@ -95,7 +95,7 @@ impl<'tcx> SaveContext<'tcx> {
     }
 
     /// Returns path to the compilation output (e.g., libfoo-12345678.rmeta)
-    pub fn compilation_output(&self, crate_name: &str) -> PathBuf {
+    pub fn compilation_output(&self, crate_name: Symbol) -> PathBuf {
         let sess = &self.tcx.sess;
         // Save-analysis is emitted per whole session, not per each crate type
         let crate_type = sess.crate_types()[0];
@@ -894,8 +894,8 @@ pub struct DumpHandler<'a> {
 }
 
 impl<'a> DumpHandler<'a> {
-    pub fn new(odir: Option<&'a Path>, cratename: &str) -> DumpHandler<'a> {
-        DumpHandler { odir, cratename: cratename.to_owned() }
+    pub fn new(odir: Option<&'a Path>, cratename: Symbol) -> DumpHandler<'a> {
+        DumpHandler { odir, cratename: cratename.to_string() }
     }
 
     fn output_file(&self, ctx: &SaveContext<'_>) -> (BufWriter<File>, PathBuf) {
@@ -960,7 +960,7 @@ impl SaveHandler for CallbackHandler<'_> {
 
 pub fn process_crate<'l, 'tcx, H: SaveHandler>(
     tcx: TyCtxt<'tcx>,
-    cratename: &str,
+    cratename: Symbol,
     input: &'l Input,
     config: Option<Config>,
     mut handler: H,
diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml
index a052f293341..d8db86c5f62 100644
--- a/compiler/rustc_session/Cargo.toml
+++ b/compiler/rustc_session/Cargo.toml
@@ -13,11 +13,13 @@ rustc_hir = { path = "../rustc_hir" }
 rustc_target = { path = "../rustc_target" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_data_structures = { path = "../rustc_data_structures" }
+rustc_index = { path = "../rustc_index" }
 rustc_span = { path = "../rustc_span" }
 rustc_fs_util = { path = "../rustc_fs_util" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_lint_defs = { path = "../rustc_lint_defs" }
 smallvec = "1.8.1"
+termize = "0.1.1"
 
 [target.'cfg(unix)'.dependencies]
 libc = "0.2"
diff --git a/compiler/rustc_session/src/code_stats.rs b/compiler/rustc_session/src/code_stats.rs
index eede4d16ea3..1085bce4475 100644
--- a/compiler/rustc_session/src/code_stats.rs
+++ b/compiler/rustc_session/src/code_stats.rs
@@ -19,7 +19,7 @@ pub enum SizeKind {
     Min,
 }
 
-#[derive(Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
 pub struct FieldInfo {
     pub name: Symbol,
     pub offset: u64,
@@ -33,6 +33,7 @@ pub enum DataTypeKind {
     Union,
     Enum,
     Closure,
+    Generator,
 }
 
 #[derive(PartialEq, Eq, Hash, Debug)]
@@ -114,7 +115,7 @@ impl CodeStats {
 
             let struct_like = match kind {
                 DataTypeKind::Struct | DataTypeKind::Closure => true,
-                DataTypeKind::Enum | DataTypeKind::Union => false,
+                DataTypeKind::Enum | DataTypeKind::Union | DataTypeKind::Generator => false,
             };
             for (i, variant_info) in variants.into_iter().enumerate() {
                 let VariantInfo { ref name, kind: _, align: _, size, ref fields } = *variant_info;
diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs
index 7d4a1e212a4..7f926f7d8bc 100644
--- a/compiler/rustc_session/src/cstore.rs
+++ b/compiler/rustc_session/src/cstore.rs
@@ -6,9 +6,10 @@ use crate::search_paths::PathKind;
 use crate::utils::NativeLibKind;
 use crate::Session;
 use rustc_ast as ast;
-use rustc_data_structures::sync::{self, MetadataRef};
-use rustc_hir::def_id::{CrateNum, DefId, StableCrateId, LOCAL_CRATE};
-use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
+use rustc_data_structures::sync::{self, MetadataRef, RwLock};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, StableCrateId, LOCAL_CRATE};
+use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions};
+use rustc_index::vec::IndexVec;
 use rustc_span::hygiene::{ExpnHash, ExpnId};
 use rustc_span::symbol::Symbol;
 use rustc_span::Span;
@@ -217,6 +218,7 @@ pub type MetadataLoaderDyn = dyn MetadataLoader + Sync;
 /// during resolve)
 pub trait CrateStore: std::fmt::Debug {
     fn as_any(&self) -> &dyn Any;
+    fn untracked_as_any(&mut self) -> &mut dyn Any;
 
     // Foreign definitions.
     // This information is safe to access, since it's hashed as part of the DefPathHash, which incr.
@@ -249,3 +251,11 @@ pub trait CrateStore: std::fmt::Debug {
 }
 
 pub type CrateStoreDyn = dyn CrateStore + sync::Sync;
+
+#[derive(Debug)]
+pub struct Untracked {
+    pub cstore: Box<CrateStoreDyn>,
+    /// Reference span for definitions.
+    pub source_span: IndexVec<LocalDefId, Span>,
+    pub definitions: RwLock<Definitions>,
+}
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index 8cb9e1a6f1a..ee492f802a7 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -129,10 +129,10 @@ pub struct FileIsNotWriteable<'a> {
 
 #[derive(Diagnostic)]
 #[diag(session_crate_name_does_not_match)]
-pub struct CrateNameDoesNotMatch<'a> {
+pub struct CrateNameDoesNotMatch {
     #[primary_span]
     pub span: Span,
-    pub s: &'a str,
+    pub s: Symbol,
     pub name: Symbol,
 }
 
@@ -151,11 +151,11 @@ pub struct CrateNameEmpty {
 
 #[derive(Diagnostic)]
 #[diag(session_invalid_character_in_create_name)]
-pub struct InvalidCharacterInCrateName<'a> {
+pub struct InvalidCharacterInCrateName {
     #[primary_span]
     pub span: Option<Span>,
     pub character: char,
-    pub crate_name: &'a str,
+    pub crate_name: Symbol,
 }
 
 #[derive(Subdiagnostic)]
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 8e9198b79df..dab9c736d14 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -368,7 +368,7 @@ mod desc {
     pub const parse_opt_panic_strategy: &str = parse_panic_strategy;
     pub const parse_oom_strategy: &str = "either `panic` or `abort`";
     pub const parse_relro_level: &str = "one of: `full`, `partial`, or `off`";
-    pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `leak`, `memory`, `memtag`, `shadow-call-stack`, or `thread`";
+    pub const parse_sanitizers: &str = "comma separated list of sanitizers: `address`, `cfi`, `hwaddress`, `kcfi`, `leak`, `memory`, `memtag`, `shadow-call-stack`, or `thread`";
     pub const parse_sanitizer_memory_track_origins: &str = "0, 1, or 2";
     pub const parse_cfguard: &str =
         "either a boolean (`yes`, `no`, `on`, `off`, etc), `checks`, or `nochecks`";
@@ -675,6 +675,7 @@ mod parse {
                 *slot |= match s {
                     "address" => SanitizerSet::ADDRESS,
                     "cfi" => SanitizerSet::CFI,
+                    "kcfi" => SanitizerSet::KCFI,
                     "leak" => SanitizerSet::LEAK,
                     "memory" => SanitizerSet::MEMORY,
                     "memtag" => SanitizerSet::MEMTAG,
diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs
index 2511bee46af..8ee3057de62 100644
--- a/compiler/rustc_session/src/output.rs
+++ b/compiler/rustc_session/src/output.rs
@@ -7,14 +7,14 @@ use crate::errors::{
 use crate::Session;
 use rustc_ast as ast;
 use rustc_span::symbol::sym;
-use rustc_span::Span;
+use rustc_span::{Span, Symbol};
 use std::path::{Path, PathBuf};
 
 pub fn out_filename(
     sess: &Session,
     crate_type: CrateType,
     outputs: &OutputFilenames,
-    crate_name: &str,
+    crate_name: Symbol,
 ) -> PathBuf {
     let default_filename = filename_for_input(sess, crate_type, crate_name, outputs);
     let out_filename = outputs
@@ -45,9 +45,9 @@ fn is_writeable(p: &Path) -> bool {
     }
 }
 
-pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) -> String {
-    let validate = |s: String, span: Option<Span>| {
-        validate_crate_name(sess, &s, span);
+pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input) -> Symbol {
+    let validate = |s: Symbol, span: Option<Span>| {
+        validate_crate_name(sess, s, span);
         s
     };
 
@@ -59,38 +59,39 @@ pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute], input: &Input)
         sess.find_by_name(attrs, sym::crate_name).and_then(|at| at.value_str().map(|s| (at, s)));
 
     if let Some(ref s) = sess.opts.crate_name {
+        let s = Symbol::intern(s);
         if let Some((attr, name)) = attr_crate_name {
-            if name.as_str() != s {
+            if name != s {
                 sess.emit_err(CrateNameDoesNotMatch { span: attr.span, s, name });
             }
         }
-        return validate(s.clone(), None);
+        return validate(s, None);
     }
 
     if let Some((attr, s)) = attr_crate_name {
-        return validate(s.to_string(), Some(attr.span));
+        return validate(s, Some(attr.span));
     }
     if let Input::File(ref path) = *input {
         if let Some(s) = path.file_stem().and_then(|s| s.to_str()) {
             if s.starts_with('-') {
                 sess.emit_err(CrateNameInvalid { s });
             } else {
-                return validate(s.replace('-', "_"), None);
+                return validate(Symbol::intern(&s.replace('-', "_")), None);
             }
         }
     }
 
-    "rust_out".to_string()
+    Symbol::intern("rust_out")
 }
 
-pub fn validate_crate_name(sess: &Session, s: &str, sp: Option<Span>) {
+pub fn validate_crate_name(sess: &Session, s: Symbol, sp: Option<Span>) {
     let mut err_count = 0;
     {
         if s.is_empty() {
             err_count += 1;
             sess.emit_err(CrateNameEmpty { span: sp });
         }
-        for c in s.chars() {
+        for c in s.as_str().chars() {
             if c.is_alphanumeric() {
                 continue;
             }
@@ -109,7 +110,7 @@ pub fn validate_crate_name(sess: &Session, s: &str, sp: Option<Span>) {
 
 pub fn filename_for_metadata(
     sess: &Session,
-    crate_name: &str,
+    crate_name: Symbol,
     outputs: &OutputFilenames,
 ) -> PathBuf {
     // If the command-line specified the path, use that directly.
@@ -132,7 +133,7 @@ pub fn filename_for_metadata(
 pub fn filename_for_input(
     sess: &Session,
     crate_type: CrateType,
-    crate_name: &str,
+    crate_name: Symbol,
     outputs: &OutputFilenames,
 ) -> PathBuf {
     let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index e99e460913e..8859b76d289 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -686,6 +686,10 @@ impl Session {
         self.opts.unstable_opts.sanitizer.contains(SanitizerSet::CFI)
     }
 
+    pub fn is_sanitizer_kcfi_enabled(&self) -> bool {
+        self.opts.unstable_opts.sanitizer.contains(SanitizerSet::KCFI)
+    }
+
     /// Check whether this compile session and crate type use static crt.
     pub fn crt_static(&self, crate_type: Option<CrateType>) -> bool {
         if !self.target.crt_static_respected {
@@ -952,6 +956,17 @@ impl Session {
     ) -> Option<Symbol> {
         attrs.iter().find(|at| at.has_name(name)).and_then(|at| at.value_str())
     }
+
+    pub fn diagnostic_width(&self) -> usize {
+        let default_column_width = 140;
+        if let Some(width) = self.opts.diagnostic_width {
+            width
+        } else if self.opts.unstable_opts.ui_testing {
+            default_column_width
+        } else {
+            termize::dimensions().map_or(default_column_width, |(w, _)| w)
+        }
+    }
 }
 
 // JUSTIFICATION: defn of the suggested wrapper fns
@@ -1533,6 +1548,14 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
         }
     }
 
+    // LLVM CFI and KCFI are mutually exclusive
+    if sess.is_sanitizer_cfi_enabled() && sess.is_sanitizer_kcfi_enabled() {
+        sess.emit_err(CannotMixAndMatchSanitizers {
+            first: "cfi".to_string(),
+            second: "kcfi".to_string(),
+        });
+    }
+
     if sess.opts.unstable_opts.stack_protector != StackProtector::None {
         if !sess.target.options.supports_stack_protector {
             sess.emit_warning(StackProtectorNotSupportedForTarget {
diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs
index 0ad1f1a0da7..e62ce2c266a 100644
--- a/compiler/rustc_span/src/def_id.rs
+++ b/compiler/rustc_span/src/def_id.rs
@@ -1,4 +1,4 @@
-use crate::HashStableContext;
+use crate::{HashStableContext, Symbol};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
 use rustc_data_structures::AtomicRef;
@@ -149,9 +149,11 @@ impl StableCrateId {
 
     /// Computes the stable ID for a crate with the given name and
     /// `-Cmetadata` arguments.
-    pub fn new(crate_name: &str, is_exe: bool, mut metadata: Vec<String>) -> StableCrateId {
+    pub fn new(crate_name: Symbol, is_exe: bool, mut metadata: Vec<String>) -> StableCrateId {
         let mut hasher = StableHasher::new();
-        crate_name.hash(&mut hasher);
+        // We must hash the string text of the crate name, not the id, as the id is not stable
+        // across builds.
+        crate_name.as_str().hash(&mut hasher);
 
         // We don't want the stable crate ID to depend on the order of
         // -C metadata arguments, so sort them:
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index cef4c6f79ce..335bfc3302f 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -491,6 +491,10 @@ impl SpanData {
     pub fn is_dummy(self) -> bool {
         self.lo.0 == 0 && self.hi.0 == 0
     }
+    #[inline]
+    pub fn is_visible(self, sm: &SourceMap) -> bool {
+        !self.is_dummy() && sm.is_span_accessible(self.span())
+    }
     /// Returns `true` if `self` fully encloses `other`.
     pub fn contains(self, other: Self) -> bool {
         self.lo <= other.lo && other.hi <= self.hi
@@ -556,6 +560,11 @@ impl Span {
         self.data_untracked().is_dummy()
     }
 
+    #[inline]
+    pub fn is_visible(self, sm: &SourceMap) -> bool {
+        self.data_untracked().is_visible(sm)
+    }
+
     /// Returns `true` if this span comes from any kind of macro, desugaring or inlining.
     #[inline]
     pub fn from_expansion(self) -> bool {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 61253845497..1fcf8c7a8bf 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -828,6 +828,7 @@ symbols! {
         item_like_imports,
         iter,
         iter_repeat,
+        kcfi,
         keyword,
         kind,
         kreg,
diff --git a/compiler/rustc_symbol_mangling/Cargo.toml b/compiler/rustc_symbol_mangling/Cargo.toml
index 2a29ad6a9e5..4e447eab02e 100644
--- a/compiler/rustc_symbol_mangling/Cargo.toml
+++ b/compiler/rustc_symbol_mangling/Cargo.toml
@@ -10,6 +10,7 @@ bitflags = "1.2.1"
 tracing = "0.1"
 punycode = "0.4.0"
 rustc-demangle = "0.1.21"
+twox-hash = "1.6.3"
 
 rustc_span = { path = "../rustc_span" }
 rustc_middle = { path = "../rustc_middle" }
diff --git a/compiler/rustc_symbol_mangling/src/typeid.rs b/compiler/rustc_symbol_mangling/src/typeid.rs
index 9228bea43f9..53983bed718 100644
--- a/compiler/rustc_symbol_mangling/src/typeid.rs
+++ b/compiler/rustc_symbol_mangling/src/typeid.rs
@@ -3,6 +3,8 @@
 
 use rustc_middle::ty::{FnSig, Ty, TyCtxt};
 use rustc_target::abi::call::FnAbi;
+use std::hash::Hasher;
+use twox_hash::XxHash64;
 
 mod typeid_itanium_cxx_abi;
 use typeid_itanium_cxx_abi::TypeIdOptions;
@@ -16,3 +18,25 @@ pub fn typeid_for_fnabi<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>)
 pub fn typeid_for_fnsig<'tcx>(tcx: TyCtxt<'tcx>, fn_sig: &FnSig<'tcx>) -> String {
     typeid_itanium_cxx_abi::typeid_for_fnsig(tcx, fn_sig, TypeIdOptions::NO_OPTIONS)
 }
+
+/// Returns an LLVM KCFI type metadata identifier for the specified FnAbi.
+pub fn kcfi_typeid_for_fnabi<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> u32 {
+    // An LLVM KCFI type metadata identifier is a 32-bit constant produced by taking the lower half
+    // of the xxHash64 of the type metadata identifier. (See llvm/llvm-project@cff5bef.)
+    let mut hash: XxHash64 = Default::default();
+    hash.write(
+        typeid_itanium_cxx_abi::typeid_for_fnabi(tcx, fn_abi, TypeIdOptions::NO_OPTIONS).as_bytes(),
+    );
+    hash.finish() as u32
+}
+
+/// Returns an LLVM KCFI type metadata identifier for the specified FnSig.
+pub fn kcfi_typeid_for_fnsig<'tcx>(tcx: TyCtxt<'tcx>, fn_sig: &FnSig<'tcx>) -> u32 {
+    // An LLVM KCFI type metadata identifier is a 32-bit constant produced by taking the lower half
+    // of the xxHash64 of the type metadata identifier. (See llvm/llvm-project@cff5bef.)
+    let mut hash: XxHash64 = Default::default();
+    hash.write(
+        typeid_itanium_cxx_abi::typeid_for_fnsig(tcx, fn_sig, TypeIdOptions::NO_OPTIONS).as_bytes(),
+    );
+    hash.finish() as u32
+}
diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_none.rs b/compiler/rustc_target/src/spec/aarch64_unknown_none.rs
index 4ae6d4120c9..aca52e1478e 100644
--- a/compiler/rustc_target/src/spec/aarch64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/aarch64_unknown_none.rs
@@ -6,13 +6,16 @@
 //
 // For example, `-C target-cpu=cortex-a53`.
 
-use super::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetOptions};
+use super::{
+    Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, SanitizerSet, Target, TargetOptions,
+};
 
 pub fn target() -> Target {
     let opts = TargetOptions {
         linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
         linker: Some("rust-lld".into()),
         features: "+strict-align,+neon,+fp-armv8".into(),
+        supported_sanitizers: SanitizerSet::KCFI,
         relocation_model: RelocModel::Static,
         disable_redzone: true,
         max_atomic_width: Some(128),
diff --git a/compiler/rustc_target/src/spec/apple_base.rs b/compiler/rustc_target/src/spec/apple_base.rs
index 7f8160b5dec..fc6a2edabb7 100644
--- a/compiler/rustc_target/src/spec/apple_base.rs
+++ b/compiler/rustc_target/src/spec/apple_base.rs
@@ -204,7 +204,7 @@ pub fn macos_llvm_target(arch: Arch) -> String {
 fn link_env_remove(arch: Arch, os: &'static str) -> StaticCow<[StaticCow<str>]> {
     // Apple platforms only officially support macOS as a host for any compilation.
     //
-    // If building for macOS, we go ahead and remove any erronous environment state
+    // If building for macOS, we go ahead and remove any erroneous environment state
     // that's only applicable to cross-OS compilation. Always leave anything for the
     // host OS alone though.
     if os == "macos" {
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index d05b8aa4200..1db1d7e85ad 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -804,7 +804,7 @@ impl ToJson for StackProbeType {
 
 bitflags::bitflags! {
     #[derive(Default, Encodable, Decodable)]
-    pub struct SanitizerSet: u8 {
+    pub struct SanitizerSet: u16 {
         const ADDRESS = 1 << 0;
         const LEAK    = 1 << 1;
         const MEMORY  = 1 << 2;
@@ -813,6 +813,7 @@ bitflags::bitflags! {
         const CFI     = 1 << 5;
         const MEMTAG  = 1 << 6;
         const SHADOWCALLSTACK = 1 << 7;
+        const KCFI    = 1 << 8;
     }
 }
 
@@ -824,6 +825,7 @@ impl SanitizerSet {
         Some(match self {
             SanitizerSet::ADDRESS => "address",
             SanitizerSet::CFI => "cfi",
+            SanitizerSet::KCFI => "kcfi",
             SanitizerSet::LEAK => "leak",
             SanitizerSet::MEMORY => "memory",
             SanitizerSet::MEMTAG => "memtag",
@@ -859,6 +861,7 @@ impl IntoIterator for SanitizerSet {
         [
             SanitizerSet::ADDRESS,
             SanitizerSet::CFI,
+            SanitizerSet::KCFI,
             SanitizerSet::LEAK,
             SanitizerSet::MEMORY,
             SanitizerSet::MEMTAG,
@@ -2327,6 +2330,7 @@ impl Target {
                             base.$key_name |= match s.as_str() {
                                 Some("address") => SanitizerSet::ADDRESS,
                                 Some("cfi") => SanitizerSet::CFI,
+                                Some("kcfi") => SanitizerSet::KCFI,
                                 Some("leak") => SanitizerSet::LEAK,
                                 Some("memory") => SanitizerSet::MEMORY,
                                 Some("memtag") => SanitizerSet::MEMTAG,
diff --git a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs
index 8dad941b534..06529c2e403 100644
--- a/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs
+++ b/compiler/rustc_target/src/spec/wasm32_unknown_unknown.rs
@@ -33,12 +33,6 @@ pub fn target() -> Target {
             // For now this target just never has an entry symbol no matter the output
             // type, so unconditionally pass this.
             "--no-entry",
-            // Rust really needs a way for users to specify exports and imports in
-            // the source code. --export-dynamic isn't the right tool for this job,
-            // however it does have the side effect of automatically exporting a lot
-            // of symbols, which approximates what people want when compiling for
-            // wasm32-unknown-unknown expect, so use it for now.
-            "--export-dynamic",
         ],
     );
     options.add_pre_link_args(
@@ -48,7 +42,6 @@ pub fn target() -> Target {
             // otherwise
             "--target=wasm32-unknown-unknown",
             "-Wl,--no-entry",
-            "-Wl,--export-dynamic",
         ],
     );
 
diff --git a/compiler/rustc_target/src/spec/wasm32_wasi.rs b/compiler/rustc_target/src/spec/wasm32_wasi.rs
index 6f0bbf0672d..a0476d542e6 100644
--- a/compiler/rustc_target/src/spec/wasm32_wasi.rs
+++ b/compiler/rustc_target/src/spec/wasm32_wasi.rs
@@ -104,6 +104,10 @@ pub fn target() -> Target {
     // `args::args()` makes the WASI API calls itself.
     options.main_needs_argc_argv = false;
 
+    // And, WASI mangles the name of "main" to distinguish between different
+    // signatures.
+    options.entry_name = "__main_void".into();
+
     Target {
         llvm_target: "wasm32-wasi".into(),
         pointer_width: 32,
diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/x86_64_unknown_none.rs
index e4d33c2b8c6..32060c35c11 100644
--- a/compiler/rustc_target/src/spec/x86_64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/x86_64_unknown_none.rs
@@ -5,7 +5,7 @@
 // features.
 
 use super::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy};
-use super::{RelroLevel, StackProbeType, Target, TargetOptions};
+use super::{RelroLevel, SanitizerSet, StackProbeType, Target, TargetOptions};
 
 pub fn target() -> Target {
     let opts = TargetOptions {
@@ -20,6 +20,7 @@ pub fn target() -> Target {
         features:
             "-mmx,-sse,-sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-3dnow,-3dnowa,-avx,-avx2,+soft-float"
                 .into(),
+        supported_sanitizers: SanitizerSet::KCFI,
         disable_redzone: true,
         panic_strategy: PanicStrategy::Abort,
         code_model: Some(CodeModel::Kernel),
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 6ea54b625bb..443d57aaf3d 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -2413,19 +2413,19 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             | ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..) => {
                 let item_name = tcx.def_path_str(item_def_id);
                 let mut multispan = MultiSpan::from(span);
+                let sm = tcx.sess.source_map();
                 if let Some(ident) = tcx.opt_item_ident(item_def_id) {
-                    let sm = tcx.sess.source_map();
                     let same_line =
                         match (sm.lookup_line(ident.span.hi()), sm.lookup_line(span.lo())) {
                             (Ok(l), Ok(r)) => l.line == r.line,
                             _ => true,
                         };
-                    if !ident.span.is_dummy() && !ident.span.overlaps(span) && !same_line {
+                    if ident.span.is_visible(sm) && !ident.span.overlaps(span) && !same_line {
                         multispan.push_span_label(ident.span, "required by a bound in this");
                     }
                 }
                 let descr = format!("required by a bound in `{}`", item_name);
-                if !span.is_dummy() {
+                if span.is_visible(sm) {
                     let msg = format!("required by this bound in `{}`", item_name);
                     multispan.push_span_label(span, msg);
                     err.span_note(multispan, &descr);
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index d3cfd61e195..ea4bf42c515 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -4,7 +4,6 @@
 
 pub mod auto_trait;
 mod chalk_fulfill;
-pub mod codegen;
 mod coherence;
 pub mod const_evaluatable;
 mod engine;
@@ -20,9 +19,9 @@ mod select;
 mod specialize;
 mod structural_match;
 mod util;
+mod vtable;
 pub mod wf;
 
-use crate::errors::DumpVTableEntries;
 use crate::infer::outlives::env::OutlivesEnvironment;
 use crate::infer::{InferCtxt, TyCtxtInferExt};
 use crate::traits::error_reporting::TypeErrCtxtExt as _;
@@ -30,15 +29,11 @@ use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_hir::lang_items::LangItem;
 use rustc_middle::ty::fold::TypeFoldable;
 use rustc_middle::ty::visit::TypeVisitable;
-use rustc_middle::ty::{
-    self, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeSuperVisitable, VtblEntry,
-};
+use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeSuperVisitable};
 use rustc_middle::ty::{InternalSubsts, SubstsRef};
-use rustc_span::{sym, Span};
-use smallvec::SmallVec;
+use rustc_span::Span;
 
 use std::fmt::Debug;
 use std::ops::ControlFlow;
@@ -567,369 +562,12 @@ fn is_impossible_method<'tcx>(
     false
 }
 
-#[derive(Clone, Debug)]
-enum VtblSegment<'tcx> {
-    MetadataDSA,
-    TraitOwnEntries { trait_ref: ty::PolyTraitRef<'tcx>, emit_vptr: bool },
-}
-
-/// Prepare the segments for a vtable
-fn prepare_vtable_segments<'tcx, T>(
-    tcx: TyCtxt<'tcx>,
-    trait_ref: ty::PolyTraitRef<'tcx>,
-    mut segment_visitor: impl FnMut(VtblSegment<'tcx>) -> ControlFlow<T>,
-) -> Option<T> {
-    // The following constraints holds for the final arrangement.
-    // 1. The whole virtual table of the first direct super trait is included as the
-    //    the prefix. If this trait doesn't have any super traits, then this step
-    //    consists of the dsa metadata.
-    // 2. Then comes the proper pointer metadata(vptr) and all own methods for all
-    //    other super traits except those already included as part of the first
-    //    direct super trait virtual table.
-    // 3. finally, the own methods of this trait.
-
-    // This has the advantage that trait upcasting to the first direct super trait on each level
-    // is zero cost, and to another trait includes only replacing the pointer with one level indirection,
-    // while not using too much extra memory.
-
-    // For a single inheritance relationship like this,
-    //   D --> C --> B --> A
-    // The resulting vtable will consists of these segments:
-    //  DSA, A, B, C, D
-
-    // For a multiple inheritance relationship like this,
-    //   D --> C --> A
-    //           \-> B
-    // The resulting vtable will consists of these segments:
-    //  DSA, A, B, B-vptr, C, D
-
-    // For a diamond inheritance relationship like this,
-    //   D --> B --> A
-    //     \-> C -/
-    // The resulting vtable will consists of these segments:
-    //  DSA, A, B, C, C-vptr, D
-
-    // For a more complex inheritance relationship like this:
-    //   O --> G --> C --> A
-    //     \     \     \-> B
-    //     |     |-> F --> D
-    //     |           \-> E
-    //     |-> N --> J --> H
-    //           \     \-> I
-    //           |-> M --> K
-    //                 \-> L
-    // The resulting vtable will consists of these segments:
-    //  DSA, A, B, B-vptr, C, D, D-vptr, E, E-vptr, F, F-vptr, G,
-    //  H, H-vptr, I, I-vptr, J, J-vptr, K, K-vptr, L, L-vptr, M, M-vptr,
-    //  N, N-vptr, O
-
-    // emit dsa segment first.
-    if let ControlFlow::Break(v) = (segment_visitor)(VtblSegment::MetadataDSA) {
-        return Some(v);
-    }
-
-    let mut emit_vptr_on_new_entry = false;
-    let mut visited = util::PredicateSet::new(tcx);
-    let predicate = trait_ref.without_const().to_predicate(tcx);
-    let mut stack: SmallVec<[(ty::PolyTraitRef<'tcx>, _, _); 5]> =
-        smallvec![(trait_ref, emit_vptr_on_new_entry, None)];
-    visited.insert(predicate);
-
-    // the main traversal loop:
-    // basically we want to cut the inheritance directed graph into a few non-overlapping slices of nodes
-    // that each node is emitted after all its descendents have been emitted.
-    // so we convert the directed graph into a tree by skipping all previously visited nodes using a visited set.
-    // this is done on the fly.
-    // Each loop run emits a slice - it starts by find a "childless" unvisited node, backtracking upwards, and it
-    // stops after it finds a node that has a next-sibling node.
-    // This next-sibling node will used as the starting point of next slice.
-
-    // Example:
-    // For a diamond inheritance relationship like this,
-    //   D#1 --> B#0 --> A#0
-    //     \-> C#1 -/
-
-    // Starting point 0 stack [D]
-    // Loop run #0: Stack after diving in is [D B A], A is "childless"
-    // after this point, all newly visited nodes won't have a vtable that equals to a prefix of this one.
-    // Loop run #0: Emitting the slice [B A] (in reverse order), B has a next-sibling node, so this slice stops here.
-    // Loop run #0: Stack after exiting out is [D C], C is the next starting point.
-    // Loop run #1: Stack after diving in is [D C], C is "childless", since its child A is skipped(already emitted).
-    // Loop run #1: Emitting the slice [D C] (in reverse order). No one has a next-sibling node.
-    // Loop run #1: Stack after exiting out is []. Now the function exits.
-
-    loop {
-        // dive deeper into the stack, recording the path
-        'diving_in: loop {
-            if let Some((inner_most_trait_ref, _, _)) = stack.last() {
-                let inner_most_trait_ref = *inner_most_trait_ref;
-                let mut direct_super_traits_iter = tcx
-                    .super_predicates_of(inner_most_trait_ref.def_id())
-                    .predicates
-                    .into_iter()
-                    .filter_map(move |(pred, _)| {
-                        pred.subst_supertrait(tcx, &inner_most_trait_ref).to_opt_poly_trait_pred()
-                    });
-
-                'diving_in_skip_visited_traits: loop {
-                    if let Some(next_super_trait) = direct_super_traits_iter.next() {
-                        if visited.insert(next_super_trait.to_predicate(tcx)) {
-                            // We're throwing away potential constness of super traits here.
-                            // FIXME: handle ~const super traits
-                            let next_super_trait = next_super_trait.map_bound(|t| t.trait_ref);
-                            stack.push((
-                                next_super_trait,
-                                emit_vptr_on_new_entry,
-                                Some(direct_super_traits_iter),
-                            ));
-                            break 'diving_in_skip_visited_traits;
-                        } else {
-                            continue 'diving_in_skip_visited_traits;
-                        }
-                    } else {
-                        break 'diving_in;
-                    }
-                }
-            }
-        }
-
-        // Other than the left-most path, vptr should be emitted for each trait.
-        emit_vptr_on_new_entry = true;
-
-        // emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level.
-        'exiting_out: loop {
-            if let Some((inner_most_trait_ref, emit_vptr, siblings_opt)) = stack.last_mut() {
-                if let ControlFlow::Break(v) = (segment_visitor)(VtblSegment::TraitOwnEntries {
-                    trait_ref: *inner_most_trait_ref,
-                    emit_vptr: *emit_vptr,
-                }) {
-                    return Some(v);
-                }
-
-                'exiting_out_skip_visited_traits: loop {
-                    if let Some(siblings) = siblings_opt {
-                        if let Some(next_inner_most_trait_ref) = siblings.next() {
-                            if visited.insert(next_inner_most_trait_ref.to_predicate(tcx)) {
-                                // We're throwing away potential constness of super traits here.
-                                // FIXME: handle ~const super traits
-                                let next_inner_most_trait_ref =
-                                    next_inner_most_trait_ref.map_bound(|t| t.trait_ref);
-                                *inner_most_trait_ref = next_inner_most_trait_ref;
-                                *emit_vptr = emit_vptr_on_new_entry;
-                                break 'exiting_out;
-                            } else {
-                                continue 'exiting_out_skip_visited_traits;
-                            }
-                        }
-                    }
-                    stack.pop();
-                    continue 'exiting_out;
-                }
-            }
-            // all done
-            return None;
-        }
-    }
-}
-
-fn dump_vtable_entries<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    sp: Span,
-    trait_ref: ty::PolyTraitRef<'tcx>,
-    entries: &[VtblEntry<'tcx>],
-) {
-    tcx.sess.emit_err(DumpVTableEntries {
-        span: sp,
-        trait_ref,
-        entries: format!("{:#?}", entries),
-    });
-}
-
-fn own_existential_vtable_entries<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId) -> &'tcx [DefId] {
-    let trait_methods = tcx
-        .associated_items(trait_def_id)
-        .in_definition_order()
-        .filter(|item| item.kind == ty::AssocKind::Fn);
-    // Now list each method's DefId (for within its trait).
-    let own_entries = trait_methods.filter_map(move |trait_method| {
-        debug!("own_existential_vtable_entry: trait_method={:?}", trait_method);
-        let def_id = trait_method.def_id;
-
-        // Some methods cannot be called on an object; skip those.
-        if !is_vtable_safe_method(tcx, trait_def_id, &trait_method) {
-            debug!("own_existential_vtable_entry: not vtable safe");
-            return None;
-        }
-
-        Some(def_id)
-    });
-
-    tcx.arena.alloc_from_iter(own_entries.into_iter())
-}
-
-/// Given a trait `trait_ref`, iterates the vtable entries
-/// that come from `trait_ref`, including its supertraits.
-fn vtable_entries<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_ref: ty::PolyTraitRef<'tcx>,
-) -> &'tcx [VtblEntry<'tcx>] {
-    debug!("vtable_entries({:?})", trait_ref);
-
-    let mut entries = vec![];
-
-    let vtable_segment_callback = |segment| -> ControlFlow<()> {
-        match segment {
-            VtblSegment::MetadataDSA => {
-                entries.extend(TyCtxt::COMMON_VTABLE_ENTRIES);
-            }
-            VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
-                let existential_trait_ref = trait_ref
-                    .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
-
-                // Lookup the shape of vtable for the trait.
-                let own_existential_entries =
-                    tcx.own_existential_vtable_entries(existential_trait_ref.def_id());
-
-                let own_entries = own_existential_entries.iter().copied().map(|def_id| {
-                    debug!("vtable_entries: trait_method={:?}", def_id);
-
-                    // The method may have some early-bound lifetimes; add regions for those.
-                    let substs = trait_ref.map_bound(|trait_ref| {
-                        InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
-                            GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
-                            GenericParamDefKind::Type { .. }
-                            | GenericParamDefKind::Const { .. } => {
-                                trait_ref.substs[param.index as usize]
-                            }
-                        })
-                    });
-
-                    // The trait type may have higher-ranked lifetimes in it;
-                    // erase them if they appear, so that we get the type
-                    // at some particular call site.
-                    let substs = tcx
-                        .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), substs);
-
-                    // It's possible that the method relies on where-clauses that
-                    // do not hold for this particular set of type parameters.
-                    // Note that this method could then never be called, so we
-                    // do not want to try and codegen it, in that case (see #23435).
-                    let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
-                    if impossible_predicates(tcx, predicates.predicates) {
-                        debug!("vtable_entries: predicates do not hold");
-                        return VtblEntry::Vacant;
-                    }
-
-                    let instance = ty::Instance::resolve_for_vtable(
-                        tcx,
-                        ty::ParamEnv::reveal_all(),
-                        def_id,
-                        substs,
-                    )
-                    .expect("resolution failed during building vtable representation");
-                    VtblEntry::Method(instance)
-                });
-
-                entries.extend(own_entries);
-
-                if emit_vptr {
-                    entries.push(VtblEntry::TraitVPtr(trait_ref));
-                }
-            }
-        }
-
-        ControlFlow::Continue(())
-    };
-
-    let _ = prepare_vtable_segments(tcx, trait_ref, vtable_segment_callback);
-
-    if tcx.has_attr(trait_ref.def_id(), sym::rustc_dump_vtable) {
-        let sp = tcx.def_span(trait_ref.def_id());
-        dump_vtable_entries(tcx, sp, trait_ref, &entries);
-    }
-
-    tcx.arena.alloc_from_iter(entries.into_iter())
-}
-
-/// Find slot base for trait methods within vtable entries of another trait
-fn vtable_trait_first_method_offset<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    key: (
-        ty::PolyTraitRef<'tcx>, // trait_to_be_found
-        ty::PolyTraitRef<'tcx>, // trait_owning_vtable
-    ),
-) -> usize {
-    let (trait_to_be_found, trait_owning_vtable) = key;
-
-    // #90177
-    let trait_to_be_found_erased = tcx.erase_regions(trait_to_be_found);
-
-    let vtable_segment_callback = {
-        let mut vtable_base = 0;
-
-        move |segment| {
-            match segment {
-                VtblSegment::MetadataDSA => {
-                    vtable_base += TyCtxt::COMMON_VTABLE_ENTRIES.len();
-                }
-                VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
-                    if tcx.erase_regions(trait_ref) == trait_to_be_found_erased {
-                        return ControlFlow::Break(vtable_base);
-                    }
-                    vtable_base += util::count_own_vtable_entries(tcx, trait_ref);
-                    if emit_vptr {
-                        vtable_base += 1;
-                    }
-                }
-            }
-            ControlFlow::Continue(())
-        }
-    };
-
-    if let Some(vtable_base) =
-        prepare_vtable_segments(tcx, trait_owning_vtable, vtable_segment_callback)
-    {
-        vtable_base
-    } else {
-        bug!("Failed to find info for expected trait in vtable");
-    }
-}
-
-/// Find slot offset for trait vptr within vtable entries of another trait
-pub fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    key: (
-        Ty<'tcx>, // trait object type whose trait owning vtable
-        Ty<'tcx>, // trait object for supertrait
-    ),
-) -> Option<usize> {
-    let (source, target) = key;
-    assert!(matches!(&source.kind(), &ty::Dynamic(..)) && !source.needs_infer());
-    assert!(matches!(&target.kind(), &ty::Dynamic(..)) && !target.needs_infer());
-
-    // this has been typecked-before, so diagnostics is not really needed.
-    let unsize_trait_did = tcx.require_lang_item(LangItem::Unsize, None);
-
-    let trait_ref = tcx.mk_trait_ref(unsize_trait_did, [source, target]);
-
-    match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), ty::Binder::dummy(trait_ref))) {
-        Ok(ImplSource::TraitUpcasting(implsrc_traitcasting)) => {
-            implsrc_traitcasting.vtable_vptr_slot
-        }
-        otherwise => bug!("expected TraitUpcasting candidate, got {otherwise:?}"),
-    }
-}
-
 pub fn provide(providers: &mut ty::query::Providers) {
     object_safety::provide(providers);
-    structural_match::provide(providers);
+    vtable::provide(providers);
     *providers = ty::query::Providers {
         specialization_graph_of: specialize::specialization_graph_provider,
         specializes: specialize::specializes,
-        codegen_select_candidate: codegen::codegen_select_candidate,
-        own_existential_vtable_entries,
-        vtable_entries,
-        vtable_trait_upcasting_coercion_new_vptr_slot,
         subst_and_check_impossible_predicates,
         is_impossible_method,
         ..*providers
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 22cd700dcb5..fda415155c4 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -19,6 +19,10 @@ use rustc_span::def_id::DefId;
 
 use crate::traits::project::{normalize_with_depth, normalize_with_depth_to};
 use crate::traits::util::{self, closure_trait_ref_and_return_type, predicate_for_trait_def};
+use crate::traits::vtable::{
+    count_own_vtable_entries, prepare_vtable_segments, vtable_trait_first_method_offset,
+    VtblSegment,
+};
 use crate::traits::{
     BuiltinDerivedObligation, ImplDerivedObligation, ImplDerivedObligationCause, ImplSource,
     ImplSourceAutoImplData, ImplSourceBuiltinData, ImplSourceClosureData,
@@ -26,7 +30,7 @@ use crate::traits::{
     ImplSourceGeneratorData, ImplSourceObjectData, ImplSourceTraitAliasData,
     ImplSourceTraitUpcastingData, ImplSourceUserDefinedData, Normalized, ObjectCastObligation,
     Obligation, ObligationCause, OutputTypeParameterMismatch, PredicateObligation, Selection,
-    SelectionError, TraitNotObjectSafe, TraitObligation, Unimplemented, VtblSegment,
+    SelectionError, TraitNotObjectSafe, TraitObligation, Unimplemented,
 };
 
 use super::BuiltinImplConditions;
@@ -583,7 +587,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         debug!(?nested, "object nested obligations");
 
-        let vtable_base = super::super::vtable_trait_first_method_offset(
+        let vtable_base = vtable_trait_first_method_offset(
             tcx,
             (unnormalized_upcast_trait_ref, ty::Binder::dummy(object_trait_ref)),
         );
@@ -904,7 +908,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         vptr_offset += TyCtxt::COMMON_VTABLE_ENTRIES.len();
                     }
                     VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
-                        vptr_offset += util::count_own_vtable_entries(tcx, trait_ref);
+                        vptr_offset += count_own_vtable_entries(tcx, trait_ref);
                         if trait_ref == upcast_trait_ref {
                             if emit_vptr {
                                 return ControlFlow::Break(Some(vptr_offset));
@@ -923,8 +927,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         };
 
         let vtable_vptr_slot =
-            super::super::prepare_vtable_segments(tcx, source_trait_ref, vtable_segment_callback)
-                .unwrap();
+            prepare_vtable_segments(tcx, source_trait_ref, vtable_segment_callback).unwrap();
 
         Ok(ImplSourceTraitUpcastingData { upcast_trait_ref, vtable_vptr_slot, nested })
     }
diff --git a/compiler/rustc_trait_selection/src/traits/structural_match.rs b/compiler/rustc_trait_selection/src/traits/structural_match.rs
index 40dbe0b3ff0..4dc08e0f9da 100644
--- a/compiler/rustc_trait_selection/src/traits/structural_match.rs
+++ b/compiler/rustc_trait_selection/src/traits/structural_match.rs
@@ -1,10 +1,5 @@
-use crate::infer::{InferCtxt, TyCtxtInferExt};
-use crate::traits::{ObligationCause, ObligationCtxt};
-
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
-use rustc_hir::lang_items::LangItem;
-use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
 use rustc_span::Span;
 use std::ops::ControlFlow;
@@ -59,41 +54,6 @@ pub fn search_for_adt_const_param_violation<'tcx>(
         .break_value()
 }
 
-/// This method returns true if and only if `adt_ty` itself has been marked as
-/// eligible for structural-match: namely, if it implements both
-/// `StructuralPartialEq` and `StructuralEq` (which are respectively injected by
-/// `#[derive(PartialEq)]` and `#[derive(Eq)]`).
-///
-/// Note that this does *not* recursively check if the substructure of `adt_ty`
-/// implements the traits.
-fn type_marked_structural<'tcx>(
-    infcx: &InferCtxt<'tcx>,
-    adt_ty: Ty<'tcx>,
-    cause: ObligationCause<'tcx>,
-) -> bool {
-    let ocx = ObligationCtxt::new(infcx);
-    // require `#[derive(PartialEq)]`
-    let structural_peq_def_id =
-        infcx.tcx.require_lang_item(LangItem::StructuralPeq, Some(cause.span));
-    ocx.register_bound(cause.clone(), ty::ParamEnv::empty(), adt_ty, structural_peq_def_id);
-    // for now, require `#[derive(Eq)]`. (Doing so is a hack to work around
-    // the type `for<'a> fn(&'a ())` failing to implement `Eq` itself.)
-    let structural_teq_def_id =
-        infcx.tcx.require_lang_item(LangItem::StructuralTeq, Some(cause.span));
-    ocx.register_bound(cause, ty::ParamEnv::empty(), adt_ty, structural_teq_def_id);
-
-    // We deliberately skip *reporting* fulfillment errors (via
-    // `report_fulfillment_errors`), for two reasons:
-    //
-    // 1. The error messages would mention `std::marker::StructuralPartialEq`
-    //    (a trait which is solely meant as an implementation detail
-    //    for now), and
-    //
-    // 2. We are sometimes doing future-incompatibility lints for
-    //    now, so we do not want unconditional errors here.
-    ocx.select_all_or_error().is_empty()
-}
-
 /// This implements the traversal over the structure of a given type to try to
 /// find instances of ADTs (specifically structs or enums) that do not implement
 /// the structural-match traits (`StructuralPartialEq` and `StructuralEq`).
@@ -249,11 +209,3 @@ impl<'tcx> TypeVisitor<'tcx> for Search<'tcx> {
         })
     }
 }
-
-pub fn provide(providers: &mut Providers) {
-    providers.has_structural_eq_impls = |tcx, ty| {
-        let infcx = tcx.infer_ctxt().build();
-        let cause = ObligationCause::dummy();
-        type_marked_structural(&infcx, ty, cause)
-    };
-}
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 51968c2d7a1..f3ca6a6c779 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -261,16 +261,6 @@ pub fn upcast_choices<'tcx>(
     supertraits(tcx, source_trait_ref).filter(|r| r.def_id() == target_trait_def_id).collect()
 }
 
-/// Given a trait `trait_ref`, returns the number of vtable entries
-/// that come from `trait_ref`, excluding its supertraits. Used in
-/// computing the vtable base for an upcast trait of a trait object.
-pub fn count_own_vtable_entries<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    trait_ref: ty::PolyTraitRef<'tcx>,
-) -> usize {
-    tcx.own_existential_vtable_entries(trait_ref.def_id()).len()
-}
-
 /// Given an upcast trait object described by `object`, returns the
 /// index of the method `method_def_id` (which should be part of
 /// `object.upcast_trait_ref`) within the vtable for `object`.
diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs
new file mode 100644
index 00000000000..41ce6cdf789
--- /dev/null
+++ b/compiler/rustc_trait_selection/src/traits/vtable.rs
@@ -0,0 +1,386 @@
+use crate::errors::DumpVTableEntries;
+use crate::traits::{impossible_predicates, is_vtable_safe_method};
+use rustc_hir::def_id::DefId;
+use rustc_hir::lang_items::LangItem;
+use rustc_infer::traits::util::PredicateSet;
+use rustc_infer::traits::ImplSource;
+use rustc_middle::ty::visit::TypeVisitable;
+use rustc_middle::ty::InternalSubsts;
+use rustc_middle::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, VtblEntry};
+use rustc_span::{sym, Span};
+use smallvec::SmallVec;
+
+use std::fmt::Debug;
+use std::ops::ControlFlow;
+
+#[derive(Clone, Debug)]
+pub(super) enum VtblSegment<'tcx> {
+    MetadataDSA,
+    TraitOwnEntries { trait_ref: ty::PolyTraitRef<'tcx>, emit_vptr: bool },
+}
+
+/// Prepare the segments for a vtable
+pub(super) fn prepare_vtable_segments<'tcx, T>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::PolyTraitRef<'tcx>,
+    mut segment_visitor: impl FnMut(VtblSegment<'tcx>) -> ControlFlow<T>,
+) -> Option<T> {
+    // The following constraints holds for the final arrangement.
+    // 1. The whole virtual table of the first direct super trait is included as the
+    //    the prefix. If this trait doesn't have any super traits, then this step
+    //    consists of the dsa metadata.
+    // 2. Then comes the proper pointer metadata(vptr) and all own methods for all
+    //    other super traits except those already included as part of the first
+    //    direct super trait virtual table.
+    // 3. finally, the own methods of this trait.
+
+    // This has the advantage that trait upcasting to the first direct super trait on each level
+    // is zero cost, and to another trait includes only replacing the pointer with one level indirection,
+    // while not using too much extra memory.
+
+    // For a single inheritance relationship like this,
+    //   D --> C --> B --> A
+    // The resulting vtable will consists of these segments:
+    //  DSA, A, B, C, D
+
+    // For a multiple inheritance relationship like this,
+    //   D --> C --> A
+    //           \-> B
+    // The resulting vtable will consists of these segments:
+    //  DSA, A, B, B-vptr, C, D
+
+    // For a diamond inheritance relationship like this,
+    //   D --> B --> A
+    //     \-> C -/
+    // The resulting vtable will consists of these segments:
+    //  DSA, A, B, C, C-vptr, D
+
+    // For a more complex inheritance relationship like this:
+    //   O --> G --> C --> A
+    //     \     \     \-> B
+    //     |     |-> F --> D
+    //     |           \-> E
+    //     |-> N --> J --> H
+    //           \     \-> I
+    //           |-> M --> K
+    //                 \-> L
+    // The resulting vtable will consists of these segments:
+    //  DSA, A, B, B-vptr, C, D, D-vptr, E, E-vptr, F, F-vptr, G,
+    //  H, H-vptr, I, I-vptr, J, J-vptr, K, K-vptr, L, L-vptr, M, M-vptr,
+    //  N, N-vptr, O
+
+    // emit dsa segment first.
+    if let ControlFlow::Break(v) = (segment_visitor)(VtblSegment::MetadataDSA) {
+        return Some(v);
+    }
+
+    let mut emit_vptr_on_new_entry = false;
+    let mut visited = PredicateSet::new(tcx);
+    let predicate = trait_ref.without_const().to_predicate(tcx);
+    let mut stack: SmallVec<[(ty::PolyTraitRef<'tcx>, _, _); 5]> =
+        smallvec![(trait_ref, emit_vptr_on_new_entry, None)];
+    visited.insert(predicate);
+
+    // the main traversal loop:
+    // basically we want to cut the inheritance directed graph into a few non-overlapping slices of nodes
+    // that each node is emitted after all its descendents have been emitted.
+    // so we convert the directed graph into a tree by skipping all previously visited nodes using a visited set.
+    // this is done on the fly.
+    // Each loop run emits a slice - it starts by find a "childless" unvisited node, backtracking upwards, and it
+    // stops after it finds a node that has a next-sibling node.
+    // This next-sibling node will used as the starting point of next slice.
+
+    // Example:
+    // For a diamond inheritance relationship like this,
+    //   D#1 --> B#0 --> A#0
+    //     \-> C#1 -/
+
+    // Starting point 0 stack [D]
+    // Loop run #0: Stack after diving in is [D B A], A is "childless"
+    // after this point, all newly visited nodes won't have a vtable that equals to a prefix of this one.
+    // Loop run #0: Emitting the slice [B A] (in reverse order), B has a next-sibling node, so this slice stops here.
+    // Loop run #0: Stack after exiting out is [D C], C is the next starting point.
+    // Loop run #1: Stack after diving in is [D C], C is "childless", since its child A is skipped(already emitted).
+    // Loop run #1: Emitting the slice [D C] (in reverse order). No one has a next-sibling node.
+    // Loop run #1: Stack after exiting out is []. Now the function exits.
+
+    loop {
+        // dive deeper into the stack, recording the path
+        'diving_in: loop {
+            if let Some((inner_most_trait_ref, _, _)) = stack.last() {
+                let inner_most_trait_ref = *inner_most_trait_ref;
+                let mut direct_super_traits_iter = tcx
+                    .super_predicates_of(inner_most_trait_ref.def_id())
+                    .predicates
+                    .into_iter()
+                    .filter_map(move |(pred, _)| {
+                        pred.subst_supertrait(tcx, &inner_most_trait_ref).to_opt_poly_trait_pred()
+                    });
+
+                'diving_in_skip_visited_traits: loop {
+                    if let Some(next_super_trait) = direct_super_traits_iter.next() {
+                        if visited.insert(next_super_trait.to_predicate(tcx)) {
+                            // We're throwing away potential constness of super traits here.
+                            // FIXME: handle ~const super traits
+                            let next_super_trait = next_super_trait.map_bound(|t| t.trait_ref);
+                            stack.push((
+                                next_super_trait,
+                                emit_vptr_on_new_entry,
+                                Some(direct_super_traits_iter),
+                            ));
+                            break 'diving_in_skip_visited_traits;
+                        } else {
+                            continue 'diving_in_skip_visited_traits;
+                        }
+                    } else {
+                        break 'diving_in;
+                    }
+                }
+            }
+        }
+
+        // Other than the left-most path, vptr should be emitted for each trait.
+        emit_vptr_on_new_entry = true;
+
+        // emit innermost item, move to next sibling and stop there if possible, otherwise jump to outer level.
+        'exiting_out: loop {
+            if let Some((inner_most_trait_ref, emit_vptr, siblings_opt)) = stack.last_mut() {
+                if let ControlFlow::Break(v) = (segment_visitor)(VtblSegment::TraitOwnEntries {
+                    trait_ref: *inner_most_trait_ref,
+                    emit_vptr: *emit_vptr,
+                }) {
+                    return Some(v);
+                }
+
+                'exiting_out_skip_visited_traits: loop {
+                    if let Some(siblings) = siblings_opt {
+                        if let Some(next_inner_most_trait_ref) = siblings.next() {
+                            if visited.insert(next_inner_most_trait_ref.to_predicate(tcx)) {
+                                // We're throwing away potential constness of super traits here.
+                                // FIXME: handle ~const super traits
+                                let next_inner_most_trait_ref =
+                                    next_inner_most_trait_ref.map_bound(|t| t.trait_ref);
+                                *inner_most_trait_ref = next_inner_most_trait_ref;
+                                *emit_vptr = emit_vptr_on_new_entry;
+                                break 'exiting_out;
+                            } else {
+                                continue 'exiting_out_skip_visited_traits;
+                            }
+                        }
+                    }
+                    stack.pop();
+                    continue 'exiting_out;
+                }
+            }
+            // all done
+            return None;
+        }
+    }
+}
+
+fn dump_vtable_entries<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    sp: Span,
+    trait_ref: ty::PolyTraitRef<'tcx>,
+    entries: &[VtblEntry<'tcx>],
+) {
+    tcx.sess.emit_err(DumpVTableEntries {
+        span: sp,
+        trait_ref,
+        entries: format!("{:#?}", entries),
+    });
+}
+
+fn own_existential_vtable_entries<'tcx>(tcx: TyCtxt<'tcx>, trait_def_id: DefId) -> &'tcx [DefId] {
+    let trait_methods = tcx
+        .associated_items(trait_def_id)
+        .in_definition_order()
+        .filter(|item| item.kind == ty::AssocKind::Fn);
+    // Now list each method's DefId (for within its trait).
+    let own_entries = trait_methods.filter_map(move |trait_method| {
+        debug!("own_existential_vtable_entry: trait_method={:?}", trait_method);
+        let def_id = trait_method.def_id;
+
+        // Some methods cannot be called on an object; skip those.
+        if !is_vtable_safe_method(tcx, trait_def_id, &trait_method) {
+            debug!("own_existential_vtable_entry: not vtable safe");
+            return None;
+        }
+
+        Some(def_id)
+    });
+
+    tcx.arena.alloc_from_iter(own_entries.into_iter())
+}
+
+/// Given a trait `trait_ref`, iterates the vtable entries
+/// that come from `trait_ref`, including its supertraits.
+fn vtable_entries<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::PolyTraitRef<'tcx>,
+) -> &'tcx [VtblEntry<'tcx>] {
+    debug!("vtable_entries({:?})", trait_ref);
+
+    let mut entries = vec![];
+
+    let vtable_segment_callback = |segment| -> ControlFlow<()> {
+        match segment {
+            VtblSegment::MetadataDSA => {
+                entries.extend(TyCtxt::COMMON_VTABLE_ENTRIES);
+            }
+            VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
+                let existential_trait_ref = trait_ref
+                    .map_bound(|trait_ref| ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref));
+
+                // Lookup the shape of vtable for the trait.
+                let own_existential_entries =
+                    tcx.own_existential_vtable_entries(existential_trait_ref.def_id());
+
+                let own_entries = own_existential_entries.iter().copied().map(|def_id| {
+                    debug!("vtable_entries: trait_method={:?}", def_id);
+
+                    // The method may have some early-bound lifetimes; add regions for those.
+                    let substs = trait_ref.map_bound(|trait_ref| {
+                        InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind {
+                            GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
+                            GenericParamDefKind::Type { .. }
+                            | GenericParamDefKind::Const { .. } => {
+                                trait_ref.substs[param.index as usize]
+                            }
+                        })
+                    });
+
+                    // The trait type may have higher-ranked lifetimes in it;
+                    // erase them if they appear, so that we get the type
+                    // at some particular call site.
+                    let substs = tcx
+                        .normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), substs);
+
+                    // It's possible that the method relies on where-clauses that
+                    // do not hold for this particular set of type parameters.
+                    // Note that this method could then never be called, so we
+                    // do not want to try and codegen it, in that case (see #23435).
+                    let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
+                    if impossible_predicates(tcx, predicates.predicates) {
+                        debug!("vtable_entries: predicates do not hold");
+                        return VtblEntry::Vacant;
+                    }
+
+                    let instance = ty::Instance::resolve_for_vtable(
+                        tcx,
+                        ty::ParamEnv::reveal_all(),
+                        def_id,
+                        substs,
+                    )
+                    .expect("resolution failed during building vtable representation");
+                    VtblEntry::Method(instance)
+                });
+
+                entries.extend(own_entries);
+
+                if emit_vptr {
+                    entries.push(VtblEntry::TraitVPtr(trait_ref));
+                }
+            }
+        }
+
+        ControlFlow::Continue(())
+    };
+
+    let _ = prepare_vtable_segments(tcx, trait_ref, vtable_segment_callback);
+
+    if tcx.has_attr(trait_ref.def_id(), sym::rustc_dump_vtable) {
+        let sp = tcx.def_span(trait_ref.def_id());
+        dump_vtable_entries(tcx, sp, trait_ref, &entries);
+    }
+
+    tcx.arena.alloc_from_iter(entries.into_iter())
+}
+
+/// Find slot base for trait methods within vtable entries of another trait
+pub(super) fn vtable_trait_first_method_offset<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    key: (
+        ty::PolyTraitRef<'tcx>, // trait_to_be_found
+        ty::PolyTraitRef<'tcx>, // trait_owning_vtable
+    ),
+) -> usize {
+    let (trait_to_be_found, trait_owning_vtable) = key;
+
+    // #90177
+    let trait_to_be_found_erased = tcx.erase_regions(trait_to_be_found);
+
+    let vtable_segment_callback = {
+        let mut vtable_base = 0;
+
+        move |segment| {
+            match segment {
+                VtblSegment::MetadataDSA => {
+                    vtable_base += TyCtxt::COMMON_VTABLE_ENTRIES.len();
+                }
+                VtblSegment::TraitOwnEntries { trait_ref, emit_vptr } => {
+                    if tcx.erase_regions(trait_ref) == trait_to_be_found_erased {
+                        return ControlFlow::Break(vtable_base);
+                    }
+                    vtable_base += count_own_vtable_entries(tcx, trait_ref);
+                    if emit_vptr {
+                        vtable_base += 1;
+                    }
+                }
+            }
+            ControlFlow::Continue(())
+        }
+    };
+
+    if let Some(vtable_base) =
+        prepare_vtable_segments(tcx, trait_owning_vtable, vtable_segment_callback)
+    {
+        vtable_base
+    } else {
+        bug!("Failed to find info for expected trait in vtable");
+    }
+}
+
+/// Find slot offset for trait vptr within vtable entries of another trait
+pub(crate) fn vtable_trait_upcasting_coercion_new_vptr_slot<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    key: (
+        Ty<'tcx>, // trait object type whose trait owning vtable
+        Ty<'tcx>, // trait object for supertrait
+    ),
+) -> Option<usize> {
+    let (source, target) = key;
+    assert!(matches!(&source.kind(), &ty::Dynamic(..)) && !source.needs_infer());
+    assert!(matches!(&target.kind(), &ty::Dynamic(..)) && !target.needs_infer());
+
+    // this has been typecked-before, so diagnostics is not really needed.
+    let unsize_trait_did = tcx.require_lang_item(LangItem::Unsize, None);
+
+    let trait_ref = tcx.mk_trait_ref(unsize_trait_did, [source, target]);
+
+    match tcx.codegen_select_candidate((ty::ParamEnv::reveal_all(), ty::Binder::dummy(trait_ref))) {
+        Ok(ImplSource::TraitUpcasting(implsrc_traitcasting)) => {
+            implsrc_traitcasting.vtable_vptr_slot
+        }
+        otherwise => bug!("expected TraitUpcasting candidate, got {otherwise:?}"),
+    }
+}
+
+/// Given a trait `trait_ref`, returns the number of vtable entries
+/// that come from `trait_ref`, excluding its supertraits. Used in
+/// computing the vtable base for an upcast trait of a trait object.
+pub(crate) fn count_own_vtable_entries<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    trait_ref: ty::PolyTraitRef<'tcx>,
+) -> usize {
+    tcx.own_existential_vtable_entries(trait_ref.def_id()).len()
+}
+
+pub(super) fn provide(providers: &mut ty::query::Providers) {
+    *providers = ty::query::Providers {
+        own_existential_vtable_entries,
+        vtable_entries,
+        vtable_trait_upcasting_coercion_new_vptr_slot,
+        ..*providers
+    };
+}
diff --git a/compiler/rustc_trait_selection/src/traits/codegen.rs b/compiler/rustc_traits/src/codegen.rs
index 0102d268b42..f8f74b732ef 100644
--- a/compiler/rustc_trait_selection/src/traits/codegen.rs
+++ b/compiler/rustc_traits/src/codegen.rs
@@ -3,15 +3,15 @@
 // seems likely that they should eventually be merged into more
 // general routines.
 
-use crate::infer::{DefiningAnchor, TyCtxtInferExt};
-use crate::traits::error_reporting::TypeErrCtxtExt;
-use crate::traits::{
-    ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, TraitEngineExt,
-    Unimplemented,
-};
+use rustc_infer::infer::{DefiningAnchor, TyCtxtInferExt};
 use rustc_infer::traits::FulfillmentErrorCode;
 use rustc_middle::traits::CodegenObligationError;
 use rustc_middle::ty::{self, TyCtxt};
+use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt;
+use rustc_trait_selection::traits::{
+    ImplSource, Obligation, ObligationCause, SelectionContext, TraitEngine, TraitEngineExt,
+    Unimplemented,
+};
 
 /// Attempts to resolve an obligation to an `ImplSource`. The result is
 /// a shallow `ImplSource` resolution, meaning that we do not
diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs
index 0ffa92f1ad5..9aa26667e7b 100644
--- a/compiler/rustc_traits/src/lib.rs
+++ b/compiler/rustc_traits/src/lib.rs
@@ -12,6 +12,7 @@ extern crate tracing;
 extern crate rustc_middle;
 
 mod chalk;
+mod codegen;
 mod dropck_outlives;
 mod evaluate_obligation;
 mod implied_outlives_bounds;
@@ -31,4 +32,5 @@ pub fn provide(p: &mut Providers) {
     normalize_projection_ty::provide(p);
     normalize_erasing_regions::provide(p);
     type_op::provide(p);
+    p.codegen_select_candidate = codegen::codegen_select_candidate;
 }
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 73c7eb6992f..d644cbccea1 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -85,7 +85,7 @@ fn fn_sig_for_fn_abi<'tcx>(
                 bound_vars,
             )
         }
-        ty::Generator(_, substs, _) => {
+        ty::Generator(did, substs, _) => {
             let sig = substs.as_generator().poly_sig();
 
             let bound_vars = tcx.mk_bound_variable_kinds(
@@ -104,10 +104,22 @@ fn fn_sig_for_fn_abi<'tcx>(
             let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs);
 
             let sig = sig.skip_binder();
-            let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
-            let state_adt_ref = tcx.adt_def(state_did);
-            let state_substs = tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]);
-            let ret_ty = tcx.mk_adt(state_adt_ref, state_substs);
+            // The `FnSig` and the `ret_ty` here is for a generators main
+            // `Generator::resume(...) -> GeneratorState` function in case we
+            // have an ordinary generator, or the `Future::poll(...) -> Poll`
+            // function in case this is a special generator backing an async construct.
+            let ret_ty = if tcx.generator_is_async(did) {
+                let state_did = tcx.require_lang_item(LangItem::Poll, None);
+                let state_adt_ref = tcx.adt_def(state_did);
+                let state_substs = tcx.intern_substs(&[sig.return_ty.into()]);
+                tcx.mk_adt(state_adt_ref, state_substs)
+            } else {
+                let state_did = tcx.require_lang_item(LangItem::GeneratorState, None);
+                let state_adt_ref = tcx.adt_def(state_did);
+                let state_substs = tcx.intern_substs(&[sig.yield_ty.into(), sig.return_ty.into()]);
+                tcx.mk_adt(state_adt_ref, state_substs)
+            };
+
             ty::Binder::bind_with_vars(
                 tcx.mk_fn_sig(
                     [env_ty, sig.resume_ty].iter(),
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index fbc055b5d23..f4672a70072 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -1,3 +1,4 @@
+use hir::def_id::DefId;
 use rustc_hir as hir;
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::{Idx, IndexVec};
@@ -6,7 +7,7 @@ use rustc_middle::ty::layout::{
     IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
 };
 use rustc_middle::ty::{
-    self, subst::SubstsRef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeVisitable,
+    self, subst::SubstsRef, AdtDef, EarlyBinder, ReprOptions, Ty, TyCtxt, TypeVisitable,
 };
 use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo};
 use rustc_span::symbol::Symbol;
@@ -814,27 +815,39 @@ fn record_layout_for_printing_outlined<'tcx>(
         );
     };
 
-    let adt_def = match *layout.ty.kind() {
-        ty::Adt(ref adt_def, _) => {
+    match *layout.ty.kind() {
+        ty::Adt(adt_def, _) => {
             debug!("print-type-size t: `{:?}` process adt", layout.ty);
-            adt_def
+            let adt_kind = adt_def.adt_kind();
+            let adt_packed = adt_def.repr().pack.is_some();
+            let (variant_infos, opt_discr_size) = variant_info_for_adt(cx, layout, adt_def);
+            record(adt_kind.into(), adt_packed, opt_discr_size, variant_infos);
+        }
+
+        ty::Generator(def_id, substs, _) => {
+            debug!("print-type-size t: `{:?}` record generator", layout.ty);
+            // Generators always have a begin/poisoned/end state with additional suspend points
+            let (variant_infos, opt_discr_size) =
+                variant_info_for_generator(cx, layout, def_id, substs);
+            record(DataTypeKind::Generator, false, opt_discr_size, variant_infos);
         }
 
         ty::Closure(..) => {
             debug!("print-type-size t: `{:?}` record closure", layout.ty);
             record(DataTypeKind::Closure, false, None, vec![]);
-            return;
         }
 
         _ => {
             debug!("print-type-size t: `{:?}` skip non-nominal", layout.ty);
-            return;
         }
     };
+}
 
-    let adt_kind = adt_def.adt_kind();
-    let adt_packed = adt_def.repr().pack.is_some();
-
+fn variant_info_for_adt<'tcx>(
+    cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+    layout: TyAndLayout<'tcx>,
+    adt_def: AdtDef<'tcx>,
+) -> (Vec<VariantInfo>, Option<Size>) {
     let build_variant_info = |n: Option<Symbol>, flds: &[Symbol], layout: TyAndLayout<'tcx>| {
         let mut min_size = Size::ZERO;
         let field_info: Vec<_> = flds
@@ -843,10 +856,7 @@ fn record_layout_for_printing_outlined<'tcx>(
             .map(|(i, &name)| {
                 let field_layout = layout.field(cx, i);
                 let offset = layout.fields.offset(i);
-                let field_end = offset + field_layout.size;
-                if min_size < field_end {
-                    min_size = field_end;
-                }
+                min_size = min_size.max(offset + field_layout.size);
                 FieldInfo {
                     name,
                     offset: offset.bytes(),
@@ -871,16 +881,9 @@ fn record_layout_for_printing_outlined<'tcx>(
                 debug!("print-type-size `{:#?}` variant {}", layout, adt_def.variant(index).name);
                 let variant_def = &adt_def.variant(index);
                 let fields: Vec<_> = variant_def.fields.iter().map(|f| f.name).collect();
-                record(
-                    adt_kind.into(),
-                    adt_packed,
-                    None,
-                    vec![build_variant_info(Some(variant_def.name), &fields, layout)],
-                );
+                (vec![build_variant_info(Some(variant_def.name), &fields, layout)], None)
             } else {
-                // (This case arises for *empty* enums; so give it
-                // zero variants.)
-                record(adt_kind.into(), adt_packed, None, vec![]);
+                (vec![], None)
             }
         }
 
@@ -898,15 +901,101 @@ fn record_layout_for_printing_outlined<'tcx>(
                     build_variant_info(Some(variant_def.name), &fields, layout.for_variant(cx, i))
                 })
                 .collect();
-            record(
-                adt_kind.into(),
-                adt_packed,
+
+            (
+                variant_infos,
                 match tag_encoding {
                     TagEncoding::Direct => Some(tag.size(cx)),
                     _ => None,
                 },
-                variant_infos,
-            );
+            )
         }
     }
 }
+
+fn variant_info_for_generator<'tcx>(
+    cx: &LayoutCx<'tcx, TyCtxt<'tcx>>,
+    layout: TyAndLayout<'tcx>,
+    def_id: DefId,
+    substs: ty::SubstsRef<'tcx>,
+) -> (Vec<VariantInfo>, Option<Size>) {
+    let Variants::Multiple { tag, ref tag_encoding, .. } = layout.variants else {
+        return (vec![], None);
+    };
+
+    let (generator, state_specific_names) = cx.tcx.generator_layout_and_saved_local_names(def_id);
+    let upvar_names = cx.tcx.closure_saved_names_of_captured_variables(def_id);
+
+    let mut upvars_size = Size::ZERO;
+    let upvar_fields: Vec<_> = substs
+        .as_generator()
+        .upvar_tys()
+        .zip(upvar_names)
+        .enumerate()
+        .map(|(field_idx, (_, name))| {
+            let field_layout = layout.field(cx, field_idx);
+            let offset = layout.fields.offset(field_idx);
+            upvars_size = upvars_size.max(offset + field_layout.size);
+            FieldInfo {
+                name: Symbol::intern(&name),
+                offset: offset.bytes(),
+                size: field_layout.size.bytes(),
+                align: field_layout.align.abi.bytes(),
+            }
+        })
+        .collect();
+
+    let variant_infos: Vec<_> = generator
+        .variant_fields
+        .iter_enumerated()
+        .map(|(variant_idx, variant_def)| {
+            let variant_layout = layout.for_variant(cx, variant_idx);
+            let mut variant_size = Size::ZERO;
+            let fields = variant_def
+                .iter()
+                .enumerate()
+                .map(|(field_idx, local)| {
+                    let field_layout = variant_layout.field(cx, field_idx);
+                    let offset = variant_layout.fields.offset(field_idx);
+                    // The struct is as large as the last field's end
+                    variant_size = variant_size.max(offset + field_layout.size);
+                    FieldInfo {
+                        name: state_specific_names.get(*local).copied().flatten().unwrap_or(
+                            Symbol::intern(&format!(".generator_field{}", local.as_usize())),
+                        ),
+                        offset: offset.bytes(),
+                        size: field_layout.size.bytes(),
+                        align: field_layout.align.abi.bytes(),
+                    }
+                })
+                .chain(upvar_fields.iter().copied())
+                .collect();
+
+            // If the variant has no state-specific fields, then it's the size of the upvars.
+            if variant_size == Size::ZERO {
+                variant_size = upvars_size;
+            }
+            // We need to add the discriminant size back into min_size, since it is subtracted
+            // later during printing.
+            variant_size += match tag_encoding {
+                TagEncoding::Direct => tag.size(cx),
+                _ => Size::ZERO,
+            };
+
+            VariantInfo {
+                name: Some(Symbol::intern(&ty::GeneratorSubsts::variant_name(variant_idx))),
+                kind: SizeKind::Exact,
+                size: variant_size.bytes(),
+                align: variant_layout.align.abi.bytes(),
+                fields,
+            }
+        })
+        .collect();
+    (
+        variant_infos,
+        match tag_encoding {
+            TagEncoding::Direct => Some(tag.size(cx)),
+            _ => None,
+        },
+    )
+}
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index cce5a79ddc8..7ad5cbc01cc 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -29,6 +29,7 @@ mod layout;
 mod layout_sanity_check;
 mod needs_drop;
 pub mod representability;
+mod structural_match;
 mod ty;
 
 pub fn provide(providers: &mut Providers) {
@@ -42,4 +43,5 @@ pub fn provide(providers: &mut Providers) {
     representability::provide(providers);
     ty::provide(providers);
     instance::provide(providers);
+    structural_match::provide(providers);
 }
diff --git a/compiler/rustc_ty_utils/src/structural_match.rs b/compiler/rustc_ty_utils/src/structural_match.rs
new file mode 100644
index 00000000000..a55bb7e7e90
--- /dev/null
+++ b/compiler/rustc_ty_utils/src/structural_match.rs
@@ -0,0 +1,44 @@
+use rustc_hir::lang_items::LangItem;
+use rustc_middle::ty::query::Providers;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_trait_selection::traits::{ObligationCause, ObligationCtxt};
+
+/// This method returns true if and only if `adt_ty` itself has been marked as
+/// eligible for structural-match: namely, if it implements both
+/// `StructuralPartialEq` and `StructuralEq` (which are respectively injected by
+/// `#[derive(PartialEq)]` and `#[derive(Eq)]`).
+///
+/// Note that this does *not* recursively check if the substructure of `adt_ty`
+/// implements the traits.
+fn has_structural_eq_impls<'tcx>(tcx: TyCtxt<'tcx>, adt_ty: Ty<'tcx>) -> bool {
+    let ref infcx = tcx.infer_ctxt().build();
+    let cause = ObligationCause::dummy();
+
+    let ocx = ObligationCtxt::new(infcx);
+    // require `#[derive(PartialEq)]`
+    let structural_peq_def_id =
+        infcx.tcx.require_lang_item(LangItem::StructuralPeq, Some(cause.span));
+    ocx.register_bound(cause.clone(), ty::ParamEnv::empty(), adt_ty, structural_peq_def_id);
+    // for now, require `#[derive(Eq)]`. (Doing so is a hack to work around
+    // the type `for<'a> fn(&'a ())` failing to implement `Eq` itself.)
+    let structural_teq_def_id =
+        infcx.tcx.require_lang_item(LangItem::StructuralTeq, Some(cause.span));
+    ocx.register_bound(cause, ty::ParamEnv::empty(), adt_ty, structural_teq_def_id);
+
+    // We deliberately skip *reporting* fulfillment errors (via
+    // `report_fulfillment_errors`), for two reasons:
+    //
+    // 1. The error messages would mention `std::marker::StructuralPartialEq`
+    //    (a trait which is solely meant as an implementation detail
+    //    for now), and
+    //
+    // 2. We are sometimes doing future-incompatibility lints for
+    //    now, so we do not want unconditional errors here.
+    ocx.select_all_or_error().is_empty()
+}
+
+pub fn provide(providers: &mut Providers) {
+    providers.has_structural_eq_impls = has_structural_eq_impls;
+}
diff --git a/config.toml.example b/config.toml.example
index ca54cbd2d68..5e1d2f2e314 100644
--- a/config.toml.example
+++ b/config.toml.example
@@ -35,9 +35,6 @@ changelog-seen = 2
 # Unless you're developing for a target where Rust CI doesn't build a compiler
 # toolchain or changing LLVM locally, you probably want to set this to true.
 #
-# This is false by default so that distributions don't unexpectedly download
-# LLVM from the internet.
-#
 # All tier 1 targets are currently supported; set this to `"if-available"` if
 # you are not sure whether you're on a tier 1 target.
 #
@@ -45,7 +42,9 @@ changelog-seen = 2
 #
 # Note that many of the LLVM options are not currently supported for
 # downloading. Currently only the "assertions" option can be toggled.
-#download-ci-llvm = false
+#
+# Defaults to "if-available" when `channel = "dev"` and "false" otherwise.
+#download-ci-llvm = "if-available"
 
 # Indicates whether LLVM rebuild should be skipped when running bootstrap. If
 # this is `false` then the compiler's LLVM will be rebuilt whenever the built
diff --git a/library/alloc/src/collections/vec_deque/into_iter.rs b/library/alloc/src/collections/vec_deque/into_iter.rs
index 55f6138cd0f..e54880e8652 100644
--- a/library/alloc/src/collections/vec_deque/into_iter.rs
+++ b/library/alloc/src/collections/vec_deque/into_iter.rs
@@ -25,6 +25,10 @@ impl<T, A: Allocator> IntoIter<T, A> {
     pub(super) fn new(inner: VecDeque<T, A>) -> Self {
         IntoIter { inner }
     }
+
+    pub(super) fn into_vecdeque(self) -> VecDeque<T, A> {
+        self.inner
+    }
 }
 
 #[stable(feature = "collection_debug", since = "1.17.0")]
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index 4866c53e7d5..4b9bd74d392 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -55,6 +55,10 @@ use self::spec_extend::SpecExtend;
 
 mod spec_extend;
 
+use self::spec_from_iter::SpecFromIter;
+
+mod spec_from_iter;
+
 #[cfg(test)]
 mod tests;
 
@@ -586,6 +590,38 @@ impl<T, A: Allocator> VecDeque<T, A> {
         VecDeque { head: 0, len: 0, buf: RawVec::with_capacity_in(capacity, alloc) }
     }
 
+    /// Creates a `VecDeque` from a raw allocation, when the initialized
+    /// part of that allocation forms a *contiguous* subslice thereof.
+    ///
+    /// For use by `vec::IntoIter::into_vecdeque`
+    ///
+    /// # Safety
+    ///
+    /// All the usual requirements on the allocated memory like in
+    /// `Vec::from_raw_parts_in`, but takes a *range* of elements that are
+    /// initialized rather than only supporting `0..len`.  Requires that
+    /// `initialized.start` ≤ `initialized.end` ≤ `capacity`.
+    #[inline]
+    pub(crate) unsafe fn from_contiguous_raw_parts_in(
+        ptr: *mut T,
+        initialized: Range<usize>,
+        capacity: usize,
+        alloc: A,
+    ) -> Self {
+        debug_assert!(initialized.start <= initialized.end);
+        debug_assert!(initialized.end <= capacity);
+
+        // SAFETY: Our safety precondition guarantees the range length won't wrap,
+        // and that the allocation is valid for use in `RawVec`.
+        unsafe {
+            VecDeque {
+                head: initialized.start,
+                len: initialized.end.unchecked_sub(initialized.start),
+                buf: RawVec::from_raw_parts_in(ptr, capacity, alloc),
+            }
+        }
+    }
+
     /// Provides a reference to the element at the given index.
     ///
     /// Element at index 0 is the front of the queue.
@@ -2699,18 +2735,8 @@ impl<T, A: Allocator> IndexMut<usize> for VecDeque<T, A> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> FromIterator<T> for VecDeque<T> {
-    #[inline]
     fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> VecDeque<T> {
-        // Since converting is O(1) now, might as well re-use that logic
-        // (including things like the `vec::IntoIter`→`Vec` specialization)
-        // especially as that could save us some monomorphiziation work
-        // if one uses the same iterators (like slice ones) with both.
-        return from_iter_via_vec(iter.into_iter());
-
-        #[inline]
-        fn from_iter_via_vec<U>(iter: impl Iterator<Item = U>) -> VecDeque<U> {
-            Vec::from_iter(iter).into()
-        }
+        SpecFromIter::spec_from_iter(iter.into_iter())
     }
 }
 
diff --git a/library/alloc/src/collections/vec_deque/spec_from_iter.rs b/library/alloc/src/collections/vec_deque/spec_from_iter.rs
new file mode 100644
index 00000000000..7650492ebda
--- /dev/null
+++ b/library/alloc/src/collections/vec_deque/spec_from_iter.rs
@@ -0,0 +1,33 @@
+use super::{IntoIter, VecDeque};
+
+/// Specialization trait used for `VecDeque::from_iter`
+pub(super) trait SpecFromIter<T, I> {
+    fn spec_from_iter(iter: I) -> Self;
+}
+
+impl<T, I> SpecFromIter<T, I> for VecDeque<T>
+where
+    I: Iterator<Item = T>,
+{
+    default fn spec_from_iter(iterator: I) -> Self {
+        // Since converting is O(1) now, just re-use the `Vec` logic for
+        // anything where we can't do something extra-special for `VecDeque`,
+        // especially as that could save us some monomorphiziation work
+        // if one uses the same iterators (like slice ones) with both.
+        crate::vec::Vec::from_iter(iterator).into()
+    }
+}
+
+impl<T> SpecFromIter<T, crate::vec::IntoIter<T>> for VecDeque<T> {
+    #[inline]
+    fn spec_from_iter(iterator: crate::vec::IntoIter<T>) -> Self {
+        iterator.into_vecdeque()
+    }
+}
+
+impl<T> SpecFromIter<T, IntoIter<T>> for VecDeque<T> {
+    #[inline]
+    fn spec_from_iter(iterator: IntoIter<T>) -> Self {
+        iterator.into_vecdeque()
+    }
+}
diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs
index 02cc7691a82..6bcde6d899c 100644
--- a/library/alloc/src/vec/into_iter.rs
+++ b/library/alloc/src/vec/into_iter.rs
@@ -1,6 +1,8 @@
 #[cfg(not(no_global_oom_handling))]
 use super::AsVecIntoIter;
 use crate::alloc::{Allocator, Global};
+#[cfg(not(no_global_oom_handling))]
+use crate::collections::VecDeque;
 use crate::raw_vec::RawVec;
 use core::array;
 use core::fmt;
@@ -132,6 +134,33 @@ impl<T, A: Allocator> IntoIter<T, A> {
     pub(crate) fn forget_remaining_elements(&mut self) {
         self.ptr = self.end;
     }
+
+    #[cfg(not(no_global_oom_handling))]
+    #[inline]
+    pub(crate) fn into_vecdeque(self) -> VecDeque<T, A> {
+        // Keep our `Drop` impl from dropping the elements and the allocator
+        let mut this = ManuallyDrop::new(self);
+
+        // SAFETY: This allocation originally came from a `Vec`, so it passes
+        // all those checks.  We have `this.buf` ≤ `this.ptr` ≤ `this.end`,
+        // so the `sub_ptr`s below cannot wrap, and will produce a well-formed
+        // range.  `end` ≤ `buf + cap`, so the range will be in-bounds.
+        // Taking `alloc` is ok because nothing else is going to look at it,
+        // since our `Drop` impl isn't going to run so there's no more code.
+        unsafe {
+            let buf = this.buf.as_ptr();
+            let initialized = if T::IS_ZST {
+                // All the pointers are the same for ZSTs, so it's fine to
+                // say that they're all at the beginning of the "allocation".
+                0..this.len()
+            } else {
+                this.ptr.sub_ptr(buf)..this.end.sub_ptr(buf)
+            };
+            let cap = this.cap;
+            let alloc = ManuallyDrop::take(&mut this.alloc);
+            VecDeque::from_contiguous_raw_parts_in(buf, initialized, cap, alloc)
+        }
+    }
 }
 
 #[stable(feature = "vec_intoiter_as_ref", since = "1.46.0")]
diff --git a/library/alloc/tests/vec_deque.rs b/library/alloc/tests/vec_deque.rs
index d04de5a074b..0b8f5281b78 100644
--- a/library/alloc/tests/vec_deque.rs
+++ b/library/alloc/tests/vec_deque.rs
@@ -1736,3 +1736,39 @@ fn test_resize_keeps_reserved_space_from_item() {
     d.resize(1, v);
     assert_eq!(d[0].capacity(), 1234);
 }
+
+#[test]
+fn test_collect_from_into_iter_keeps_allocation() {
+    let mut v = Vec::with_capacity(13);
+    v.extend(0..7);
+    check(v.as_ptr(), v.last().unwrap(), v.into_iter());
+
+    let mut v = VecDeque::with_capacity(13);
+    v.extend(0..7);
+    check(&v[0], &v[v.len() - 1], v.into_iter());
+
+    fn check(buf: *const i32, last: *const i32, mut it: impl Iterator<Item = i32>) {
+        assert_eq!(it.next(), Some(0));
+        assert_eq!(it.next(), Some(1));
+
+        let mut v: VecDeque<i32> = it.collect();
+        assert_eq!(v.capacity(), 13);
+        assert_eq!(v.as_slices().0.as_ptr(), buf.wrapping_add(2));
+        assert_eq!(&v[v.len() - 1] as *const _, last);
+
+        assert_eq!(v.as_slices(), ([2, 3, 4, 5, 6].as_slice(), [].as_slice()));
+        v.push_front(7);
+        assert_eq!(v.as_slices(), ([7, 2, 3, 4, 5, 6].as_slice(), [].as_slice()));
+        v.push_front(8);
+        assert_eq!(v.as_slices(), ([8, 7, 2, 3, 4, 5, 6].as_slice(), [].as_slice()));
+
+        // Now that we've adding thing in place of the two that we removed from
+        // the front of the iterator, we're back to matching the buffer pointer.
+        assert_eq!(v.as_slices().0.as_ptr(), buf);
+        assert_eq!(&v[v.len() - 1] as *const _, last);
+
+        v.push_front(9);
+        assert_eq!(v.as_slices(), ([9].as_slice(), [8, 7, 2, 3, 4, 5, 6].as_slice()));
+        assert_eq!(v.capacity(), 13);
+    }
+}
diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs
index 06dca7e59a2..398437d9a02 100644
--- a/library/core/src/clone.rs
+++ b/library/core/src/clone.rs
@@ -176,7 +176,6 @@ pub struct AssertParamIsCopy<T: Copy + ?Sized> {
 /// are implemented in `traits::SelectionContext::copy_clone_conditions()`
 /// in `rustc_trait_selection`.
 mod impls {
-
     use super::Clone;
 
     macro_rules! impl_clone {
@@ -185,7 +184,7 @@ mod impls {
                 #[stable(feature = "rust1", since = "1.0.0")]
                 #[rustc_const_unstable(feature = "const_clone", issue = "91805")]
                 impl const Clone for $t {
-                    #[inline]
+                    #[inline(always)]
                     fn clone(&self) -> Self {
                         *self
                     }
@@ -213,7 +212,7 @@ mod impls {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_clone", issue = "91805")]
     impl<T: ?Sized> const Clone for *const T {
-        #[inline]
+        #[inline(always)]
         fn clone(&self) -> Self {
             *self
         }
@@ -222,7 +221,7 @@ mod impls {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_clone", issue = "91805")]
     impl<T: ?Sized> const Clone for *mut T {
-        #[inline]
+        #[inline(always)]
         fn clone(&self) -> Self {
             *self
         }
@@ -232,7 +231,7 @@ mod impls {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_clone", issue = "91805")]
     impl<T: ?Sized> const Clone for &T {
-        #[inline]
+        #[inline(always)]
         #[rustc_diagnostic_item = "noop_method_clone"]
         fn clone(&self) -> Self {
             *self
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index 33493964bad..f95b880df34 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -99,7 +99,7 @@ pub use num::FloatToInt;
 /// ```
 #[stable(feature = "convert_id", since = "1.33.0")]
 #[rustc_const_stable(feature = "const_identity", since = "1.33.0")]
-#[inline]
+#[inline(always)]
 pub const fn identity<T>(x: T) -> T {
     x
 }
@@ -789,6 +789,7 @@ where
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> AsRef<[T]> for [T] {
+    #[inline(always)]
     fn as_ref(&self) -> &[T] {
         self
     }
@@ -796,6 +797,7 @@ impl<T> AsRef<[T]> for [T] {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> AsMut<[T]> for [T] {
+    #[inline(always)]
     fn as_mut(&mut self) -> &mut [T] {
         self
     }
@@ -803,7 +805,7 @@ impl<T> AsMut<[T]> for [T] {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl AsRef<str> for str {
-    #[inline]
+    #[inline(always)]
     fn as_ref(&self) -> &str {
         self
     }
@@ -811,7 +813,7 @@ impl AsRef<str> for str {
 
 #[stable(feature = "as_mut_str_for_str", since = "1.51.0")]
 impl AsMut<str> for str {
-    #[inline]
+    #[inline(always)]
     fn as_mut(&mut self) -> &mut str {
         self
     }
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index c53175ba4f3..e8d724ab1ef 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -160,7 +160,7 @@ pub const unsafe fn unreachable_unchecked() -> ! {
 /// ```
 ///
 /// [`thread::yield_now`]: ../../std/thread/fn.yield_now.html
-#[inline]
+#[inline(always)]
 #[stable(feature = "renamed_spin_loop", since = "1.49.0")]
 pub fn spin_loop() {
     #[cfg(target_arch = "x86")]
@@ -345,6 +345,7 @@ pub const fn black_box<T>(dummy: T) -> T {
 #[unstable(feature = "hint_must_use", issue = "94745")]
 #[rustc_const_unstable(feature = "hint_must_use", issue = "94745")]
 #[must_use] // <-- :)
+#[inline(always)]
 pub const fn must_use<T>(value: T) -> T {
     value
 }
diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs
index 84d83ee3969..e31669b3924 100644
--- a/library/core/src/iter/traits/accum.rs
+++ b/library/core/src/iter/traits/accum.rs
@@ -10,6 +10,10 @@ use crate::num::Wrapping;
 /// [`sum()`]: Iterator::sum
 /// [`FromIterator`]: iter::FromIterator
 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
+#[rustc_on_unimplemented(
+    message = "a value of type `{Self}` cannot be made by summing an iterator over elements of type `{A}`",
+    label = "value of type `{Self}` cannot be made by summing a `std::iter::Iterator<Item={A}>`"
+)]
 pub trait Sum<A = Self>: Sized {
     /// Method which takes an iterator and generates `Self` from the elements by
     /// "summing up" the items.
@@ -27,6 +31,10 @@ pub trait Sum<A = Self>: Sized {
 /// [`product()`]: Iterator::product
 /// [`FromIterator`]: iter::FromIterator
 #[stable(feature = "iter_arith_traits", since = "1.12.0")]
+#[rustc_on_unimplemented(
+    message = "a value of type `{Self}` cannot be made by multiplying all elements of type `{A}` from an iterator",
+    label = "value of type `{Self}` cannot be made by multiplying all elements from a `std::iter::Iterator<Item={A}>`"
+)]
 pub trait Product<A = Self>: Sized {
     /// Method which takes an iterator and generates `Self` from the elements by
     /// multiplying the items.
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index b2328b001de..ac7f579ebb5 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -4,12 +4,14 @@
 
 use crate::ascii;
 use crate::convert::TryInto;
-use crate::error::Error;
 use crate::intrinsics;
 use crate::mem;
 use crate::ops::{Add, Mul, Sub};
 use crate::str::FromStr;
 
+#[cfg(not(no_fp_fmt_parse))]
+use crate::error::Error;
+
 // Used because the `?` operator is not allowed in a const context.
 macro_rules! try_opt {
     ($e:expr) => {
diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs
index a5e5b13b336..eb2a92f4644 100644
--- a/library/core/src/ops/mod.rs
+++ b/library/core/src/ops/mod.rs
@@ -17,10 +17,10 @@
 //! should have some resemblance to multiplication (and share expected
 //! properties like associativity).
 //!
-//! Note that the `&&` and `||` operators short-circuit, i.e., they only
-//! evaluate their second operand if it contributes to the result. Since this
-//! behavior is not enforceable by traits, `&&` and `||` are not supported as
-//! overloadable operators.
+//! Note that the `&&` and `||` operators are currently not supported for
+//! overloading. Due to their short circuiting nature, they require a different
+//! design from traits for other operators like [`BitAnd`]. Designs for them are
+//! under discussion.
 //!
 //! Many of the operators take their operands by value. In non-generic
 //! contexts involving built-in types, this is usually not a problem.
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 76603e1018d..d348135991a 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -45,7 +45,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")]
-    #[inline]
+    #[inline(always)]
     pub const fn cast<U>(self) -> *const U {
         self as _
     }
@@ -95,6 +95,7 @@ impl<T: ?Sized> *const T {
     /// refactored.
     #[stable(feature = "ptr_const_cast", since = "1.65.0")]
     #[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")]
+    #[inline(always)]
     pub const fn cast_mut(self) -> *mut T {
         self as _
     }
@@ -126,6 +127,7 @@ impl<T: ?Sized> *const T {
         note = "replaced by the `exposed_addr` method, or update your code \
             to follow the strict provenance rules using its APIs"
     )]
+    #[inline(always)]
     pub fn to_bits(self) -> usize
     where
         T: Sized,
@@ -155,6 +157,7 @@ impl<T: ?Sized> *const T {
             your code to follow the strict provenance rules using its APIs"
     )]
     #[allow(fuzzy_provenance_casts)] // this is an unstable and semi-deprecated cast function
+    #[inline(always)]
     pub fn from_bits(bits: usize) -> Self
     where
         T: Sized,
@@ -186,7 +189,7 @@ impl<T: ?Sized> *const T {
     /// might change in the future (including possibly weakening this so it becomes wholly
     /// equivalent to `self as usize`). See the [module documentation][crate::ptr] for details.
     #[must_use]
-    #[inline]
+    #[inline(always)]
     #[unstable(feature = "strict_provenance", issue = "95228")]
     pub fn addr(self) -> usize
     where
@@ -223,7 +226,7 @@ impl<T: ?Sized> *const T {
     ///
     /// [`from_exposed_addr`]: from_exposed_addr
     #[must_use]
-    #[inline]
+    #[inline(always)]
     #[unstable(feature = "strict_provenance", issue = "95228")]
     pub fn expose_addr(self) -> usize
     where
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 89b11637eca..48b2e88da28 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -613,7 +613,7 @@ pub const fn invalid_mut<T>(addr: usize) -> *mut T {
 /// This API and its claimed semantics are part of the Strict Provenance experiment, see the
 /// [module documentation][crate::ptr] for details.
 #[must_use]
-#[inline]
+#[inline(always)]
 #[unstable(feature = "strict_provenance", issue = "95228")]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 #[allow(fuzzy_provenance_casts)] // this *is* the strict provenance API one should use instead
@@ -651,7 +651,7 @@ where
 /// This API and its claimed semantics are part of the Strict Provenance experiment, see the
 /// [module documentation][crate::ptr] for details.
 #[must_use]
-#[inline]
+#[inline(always)]
 #[unstable(feature = "strict_provenance", issue = "95228")]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 #[allow(fuzzy_provenance_casts)] // this *is* the strict provenance API one should use instead
@@ -1769,7 +1769,7 @@ pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usiz
 /// (which is what the `PartialEq for &T` implementation does).
 ///
 /// When comparing wide pointers, both the address and the metadata are tested for equality.
-/// However, note that comparing trait object pointers (`*const dyn Trait`) is unrealiable: pointers
+/// However, note that comparing trait object pointers (`*const dyn Trait`) is unreliable: pointers
 /// to values of the same underlying type can compare inequal (because vtables are duplicated in
 /// multiple codegen units), and pointers to values of *different* underlying type can compare equal
 /// (since identical vtables can be deduplicated within a codegen unit).
@@ -1801,7 +1801,7 @@ pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usiz
 /// assert!(!std::ptr::eq(&a[0..2], &a[1..3]));
 /// ```
 #[stable(feature = "ptr_eq", since = "1.17.0")]
-#[inline]
+#[inline(always)]
 pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
     a == b
 }
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index b03cad18e4a..c924a90b1ff 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -100,6 +100,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")]
+    #[inline(always)]
     pub const fn cast_const(self) -> *const T {
         self as _
     }
@@ -132,6 +133,7 @@ impl<T: ?Sized> *mut T {
         note = "replaced by the `exposed_addr` method, or update your code \
             to follow the strict provenance rules using its APIs"
     )]
+    #[inline(always)]
     pub fn to_bits(self) -> usize
     where
         T: Sized,
@@ -161,6 +163,7 @@ impl<T: ?Sized> *mut T {
             update your code to follow the strict provenance rules using its APIs"
     )]
     #[allow(fuzzy_provenance_casts)] // this is an unstable and semi-deprecated cast function
+    #[inline(always)]
     pub fn from_bits(bits: usize) -> Self
     where
         T: Sized,
@@ -192,7 +195,7 @@ impl<T: ?Sized> *mut T {
     /// might change in the future (including possibly weakening this so it becomes wholly
     /// equivalent to `self as usize`). See the [module documentation][crate::ptr] for details.
     #[must_use]
-    #[inline]
+    #[inline(always)]
     #[unstable(feature = "strict_provenance", issue = "95228")]
     pub fn addr(self) -> usize
     where
@@ -229,7 +232,7 @@ impl<T: ?Sized> *mut T {
     ///
     /// [`from_exposed_addr_mut`]: from_exposed_addr_mut
     #[must_use]
-    #[inline]
+    #[inline(always)]
     #[unstable(feature = "strict_provenance", issue = "95228")]
     pub fn expose_addr(self) -> usize
     where
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index c18264d13eb..c4348169c78 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -330,7 +330,7 @@ impl<T: ?Sized> NonNull<T> {
     #[stable(feature = "nonnull", since = "1.25.0")]
     #[rustc_const_stable(feature = "const_nonnull_as_ptr", since = "1.32.0")]
     #[must_use]
-    #[inline]
+    #[inline(always)]
     pub const fn as_ptr(self) -> *mut T {
         self.pointer as *mut T
     }
@@ -378,7 +378,7 @@ impl<T: ?Sized> NonNull<T> {
     #[stable(feature = "nonnull", since = "1.25.0")]
     #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
     #[must_use]
-    #[inline]
+    #[inline(always)]
     pub const unsafe fn as_ref<'a>(&self) -> &'a T {
         // SAFETY: the caller must guarantee that `self` meets all the
         // requirements for a reference.
@@ -429,7 +429,7 @@ impl<T: ?Sized> NonNull<T> {
     #[stable(feature = "nonnull", since = "1.25.0")]
     #[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]
     #[must_use]
-    #[inline]
+    #[inline(always)]
     pub const unsafe fn as_mut<'a>(&mut self) -> &'a mut T {
         // SAFETY: the caller must guarantee that `self` meets all the
         // requirements for a mutable reference.
@@ -703,7 +703,7 @@ impl<T> NonNull<[T]> {
 #[stable(feature = "nonnull", since = "1.25.0")]
 #[rustc_const_unstable(feature = "const_clone", issue = "91805")]
 impl<T: ?Sized> const Clone for NonNull<T> {
-    #[inline]
+    #[inline(always)]
     fn clone(&self) -> Self {
         *self
     }
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 04486ed2d14..d9281a9252c 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -465,7 +465,7 @@ impl<T> [T] {
     /// [`as_mut_ptr`]: slice::as_mut_ptr
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_slice_as_ptr", since = "1.32.0")]
-    #[inline]
+    #[inline(always)]
     #[must_use]
     pub const fn as_ptr(&self) -> *const T {
         self as *const [T] as *const T
@@ -495,7 +495,7 @@ impl<T> [T] {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
     #[rustc_allow_const_fn_unstable(const_mut_refs)]
-    #[inline]
+    #[inline(always)]
     #[must_use]
     pub const fn as_mut_ptr(&mut self) -> *mut T {
         self as *mut [T] as *mut T
@@ -3468,10 +3468,11 @@ impl<T> [T] {
     /// maintained.
     ///
     /// This method splits the slice into three distinct slices: prefix, correctly aligned middle
-    /// slice of a new type, and the suffix slice. The method may make the middle slice the greatest
-    /// length possible for a given type and input slice, but only your algorithm's performance
-    /// should depend on that, not its correctness. It is permissible for all of the input data to
-    /// be returned as the prefix or suffix slice.
+    /// slice of a new type, and the suffix slice. How exactly the slice is split up is not
+    /// specified; the middle part may be smaller than necessary. However, if this fails to return a
+    /// maximal middle part, that is because code is running in a context where performance does not
+    /// matter, such as a sanitizer attempting to find alignment bugs. Regular code running
+    /// in a default (debug or release) execution *will* return a maximal middle part.
     ///
     /// This method has no purpose when either input element `T` or output element `U` are
     /// zero-sized and will return the original slice without splitting anything.
@@ -3529,10 +3530,11 @@ impl<T> [T] {
     /// types is maintained.
     ///
     /// This method splits the slice into three distinct slices: prefix, correctly aligned middle
-    /// slice of a new type, and the suffix slice. The method may make the middle slice the greatest
-    /// length possible for a given type and input slice, but only your algorithm's performance
-    /// should depend on that, not its correctness. It is permissible for all of the input data to
-    /// be returned as the prefix or suffix slice.
+    /// slice of a new type, and the suffix slice. How exactly the slice is split up is not
+    /// specified; the middle part may be smaller than necessary. However, if this fails to return a
+    /// maximal middle part, that is because code is running in a context where performance does not
+    /// matter, such as a sanitizer attempting to find alignment bugs. Regular code running
+    /// in a default (debug or release) execution *will* return a maximal middle part.
     ///
     /// This method has no purpose when either input element `T` or output element `U` are
     /// zero-sized and will return the original slice without splitting anything.
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index c0167388713..45fd2caae52 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -396,7 +396,7 @@ impl str {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "rustc_str_as_ptr", since = "1.32.0")]
     #[must_use]
-    #[inline]
+    #[inline(always)]
     pub const fn as_ptr(&self) -> *const u8 {
         self as *const str as *const u8
     }
@@ -411,7 +411,7 @@ impl str {
     /// modified in a way that it remains valid UTF-8.
     #[stable(feature = "str_as_mut_ptr", since = "1.36.0")]
     #[must_use]
-    #[inline]
+    #[inline(always)]
     pub fn as_mut_ptr(&mut self) -> *mut u8 {
         self as *mut str as *mut u8
     }
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index b8959316de1..4748ac9d97e 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -1551,3 +1551,19 @@ fn hiberfil_sys() {
     fs::metadata(hiberfil).unwrap();
     assert_eq!(true, hiberfil.exists());
 }
+
+/// Test that two different ways of obtaining the FileType give the same result.
+/// Cf. https://github.com/rust-lang/rust/issues/104900
+#[test]
+fn test_eq_direntry_metadata() {
+    let tmpdir = tmpdir();
+    let file_path = tmpdir.join("file");
+    File::create(file_path).unwrap();
+    for e in fs::read_dir(tmpdir.path()).unwrap() {
+        let e = e.unwrap();
+        let p = e.path();
+        let ft1 = e.file_type().unwrap();
+        let ft2 = p.metadata().unwrap().file_type();
+        assert_eq!(ft1, ft2);
+    }
+}
diff --git a/library/std/src/sys/itron/condvar.rs b/library/std/src/sys/itron/condvar.rs
index f70aa434e48..7a47cc6696a 100644
--- a/library/std/src/sys/itron/condvar.rs
+++ b/library/std/src/sys/itron/condvar.rs
@@ -71,7 +71,7 @@ impl Condvar {
             }
         }
 
-        unsafe { mutex.lock() };
+        mutex.lock();
     }
 
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
@@ -109,7 +109,7 @@ impl Condvar {
         // we woke up because of `notify_*`.
         let success = self.waiters.with_locked(|waiters| unsafe { !waiters.remove(waiter) });
 
-        unsafe { mutex.lock() };
+        mutex.lock();
         success
     }
 }
diff --git a/library/std/src/sys/itron/mutex.rs b/library/std/src/sys/itron/mutex.rs
index f2eed8e771c..1f6cc419476 100644
--- a/library/std/src/sys/itron/mutex.rs
+++ b/library/std/src/sys/itron/mutex.rs
@@ -72,7 +72,7 @@ pub(super) struct MutexGuard<'a>(&'a Mutex);
 impl<'a> MutexGuard<'a> {
     #[inline]
     pub(super) fn lock(x: &'a Mutex) -> Self {
-        unsafe { x.lock() };
+        x.lock();
         Self(x)
     }
 }
diff --git a/library/std/src/sys/itron/thread.rs b/library/std/src/sys/itron/thread.rs
index d28f57f33be..c2b36680872 100644
--- a/library/std/src/sys/itron/thread.rs
+++ b/library/std/src/sys/itron/thread.rs
@@ -11,18 +11,25 @@ use crate::{
     ffi::CStr,
     hint, io,
     mem::ManuallyDrop,
+    ptr::NonNull,
     sync::atomic::{AtomicUsize, Ordering},
     sys::thread_local_dtor::run_dtors,
     time::Duration,
 };
 
 pub struct Thread {
-    inner: ManuallyDrop<Box<ThreadInner>>,
+    p_inner: NonNull<ThreadInner>,
 
     /// The ID of the underlying task.
     task: abi::ID,
 }
 
+// Safety: There's nothing in `Thread` that ties it to the original creator. It
+//         can be dropped by any threads.
+unsafe impl Send for Thread {}
+// Safety: `Thread` provides no methods that take `&self`.
+unsafe impl Sync for Thread {}
+
 /// State data shared between a parent thread and child thread. It's dropped on
 /// a transition to one of the final states.
 struct ThreadInner {
@@ -90,8 +97,9 @@ impl Thread {
         });
 
         unsafe extern "C" fn trampoline(exinf: isize) {
+            let p_inner: *mut ThreadInner = crate::ptr::from_exposed_addr_mut(exinf as usize);
             // Safety: `ThreadInner` is alive at this point
-            let inner = unsafe { &*(exinf as *const ThreadInner) };
+            let inner = unsafe { &*p_inner };
 
             // Safety: Since `trampoline` is called only once for each
             //         `ThreadInner` and only `trampoline` touches `start`,
@@ -119,13 +127,13 @@ impl Thread {
                     // No one will ever join, so we'll ask the collector task to
                     // delete the task.
 
-                    // In this case, `inner`'s ownership has been moved to us,
-                    // And we are responsible for dropping it. The acquire
+                    // In this case, `*p_inner`'s ownership has been moved to
+                    // us, and we are responsible for dropping it. The acquire
                     // ordering is not necessary because the parent thread made
                     // no memory access needing synchronization since the call
                     // to `acre_tsk`.
                     // Safety: See above.
-                    let _ = unsafe { Box::from_raw(inner as *const _ as *mut ThreadInner) };
+                    let _ = unsafe { Box::from_raw(p_inner) };
 
                     // Safety: There are no pinned references to the stack
                     unsafe { terminate_and_delete_current_task() };
@@ -162,13 +170,14 @@ impl Thread {
             }
         }
 
-        let inner_ptr = (&*inner) as *const ThreadInner;
+        // Safety: `Box::into_raw` returns a non-null pointer
+        let p_inner = unsafe { NonNull::new_unchecked(Box::into_raw(inner)) };
 
         let new_task = ItronError::err_if_negative(unsafe {
             abi::acre_tsk(&abi::T_CTSK {
                 // Activate this task immediately
                 tskatr: abi::TA_ACT,
-                exinf: inner_ptr as abi::EXINF,
+                exinf: p_inner.as_ptr().expose_addr() as abi::EXINF,
                 // The entry point
                 task: Some(trampoline),
                 // Inherit the calling task's base priority
@@ -180,7 +189,7 @@ impl Thread {
         })
         .map_err(|e| e.as_io_error())?;
 
-        Ok(Self { inner: ManuallyDrop::new(inner), task: new_task })
+        Ok(Self { p_inner, task: new_task })
     }
 
     pub fn yield_now() {
@@ -197,8 +206,9 @@ impl Thread {
         }
     }
 
-    pub fn join(mut self) {
-        let inner = &*self.inner;
+    pub fn join(self) {
+        // Safety: `ThreadInner` is alive at this point
+        let inner = unsafe { self.p_inner.as_ref() };
         // Get the current task ID. Panicking here would cause a resource leak,
         // so just abort on failure.
         let current_task = task::current_task_id_aborting();
@@ -243,8 +253,8 @@ impl Thread {
         unsafe { terminate_and_delete_task(self.task) };
 
         // In either case, we are responsible for dropping `inner`.
-        // Safety: The contents of `self.inner` will not be accessed hereafter
-        let _inner = unsafe { ManuallyDrop::take(&mut self.inner) };
+        // Safety: The contents of `*p_inner` will not be accessed hereafter
+        let _inner = unsafe { Box::from_raw(self.p_inner.as_ptr()) };
 
         // Skip the destructor (because it would attempt to detach the thread)
         crate::mem::forget(self);
@@ -253,13 +263,16 @@ impl Thread {
 
 impl Drop for Thread {
     fn drop(&mut self) {
+        // Safety: `ThreadInner` is alive at this point
+        let inner = unsafe { self.p_inner.as_ref() };
+
         // Detach the thread.
-        match self.inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::Acquire) {
+        match inner.lifecycle.swap(LIFECYCLE_DETACHED_OR_JOINED, Ordering::Acquire) {
             LIFECYCLE_INIT => {
                 // [INIT → DETACHED]
                 // When the time comes, the child will figure out that no
                 // one will ever join it.
-                // The ownership of `self.inner` is moved to the child thread.
+                // The ownership of `*p_inner` is moved to the child thread.
                 // However, the release ordering is not necessary because we
                 // made no memory access needing synchronization since the call
                 // to `acre_tsk`.
@@ -278,10 +291,9 @@ impl Drop for Thread {
                 //         delete by entering the `FINISHED` state.
                 unsafe { terminate_and_delete_task(self.task) };
 
-                // Wwe are responsible for dropping `inner`.
-                // Safety: The contents of `self.inner` will not be accessed
-                //         hereafter
-                unsafe { ManuallyDrop::drop(&mut self.inner) };
+                // Wwe are responsible for dropping `*p_inner`.
+                // Safety: The contents of `*p_inner` will not be accessed hereafter
+                let _ = unsafe { Box::from_raw(self.p_inner.as_ptr()) };
             }
             _ => unsafe { hint::unreachable_unchecked() },
         }
diff --git a/library/std/src/sys/sgx/mod.rs b/library/std/src/sys/sgx/mod.rs
index 01e4ffe3dfc..63e070207cd 100644
--- a/library/std/src/sys/sgx/mod.rs
+++ b/library/std/src/sys/sgx/mod.rs
@@ -34,6 +34,7 @@ pub mod process;
 pub mod stdio;
 pub mod thread;
 pub mod thread_local_key;
+pub mod thread_parker;
 pub mod time;
 
 mod condvar;
diff --git a/library/std/src/sys/sgx/thread.rs b/library/std/src/sys/sgx/thread.rs
index d745a619614..579f758c6cc 100644
--- a/library/std/src/sys/sgx/thread.rs
+++ b/library/std/src/sys/sgx/thread.rs
@@ -65,39 +65,36 @@ mod task_queue {
 /// execution. The signal is sent once all TLS destructors have finished at
 /// which point no new thread locals should be created.
 pub mod wait_notify {
-    use super::super::waitqueue::{SpinMutex, WaitQueue, WaitVariable};
+    use super::super::thread_parker::Parker;
+    use crate::pin::Pin;
     use crate::sync::Arc;
 
-    pub struct Notifier(Arc<SpinMutex<WaitVariable<bool>>>);
+    pub struct Notifier(Arc<Parker>);
 
     impl Notifier {
         /// Notify the waiter. The waiter is either notified right away (if
         /// currently blocked in `Waiter::wait()`) or later when it calls the
         /// `Waiter::wait()` method.
         pub fn notify(self) {
-            let mut guard = self.0.lock();
-            *guard.lock_var_mut() = true;
-            let _ = WaitQueue::notify_one(guard);
+            Pin::new(&*self.0).unpark()
         }
     }
 
-    pub struct Waiter(Arc<SpinMutex<WaitVariable<bool>>>);
+    pub struct Waiter(Arc<Parker>);
 
     impl Waiter {
         /// Wait for a notification. If `Notifier::notify()` has already been
         /// called, this will return immediately, otherwise the current thread
         /// is blocked until notified.
         pub fn wait(self) {
-            let guard = self.0.lock();
-            if *guard.lock_var() {
-                return;
-            }
-            WaitQueue::wait(guard, || {});
+            // This is not actually `unsafe`, but it uses the `Parker` API,
+            // which needs `unsafe` on some platforms.
+            unsafe { Pin::new(&*self.0).park() }
         }
     }
 
     pub fn new() -> (Notifier, Waiter) {
-        let inner = Arc::new(SpinMutex::new(WaitVariable::new(false)));
+        let inner = Arc::new(Parker::new_internal());
         (Notifier(inner.clone()), Waiter(inner))
     }
 }
diff --git a/library/std/src/sys/sgx/thread_parker.rs b/library/std/src/sys/sgx/thread_parker.rs
new file mode 100644
index 00000000000..1c55bcffb1e
--- /dev/null
+++ b/library/std/src/sys/sgx/thread_parker.rs
@@ -0,0 +1,107 @@
+//! Thread parking based on SGX events.
+
+use super::abi::{thread, usercalls};
+use crate::io::ErrorKind;
+use crate::pin::Pin;
+use crate::ptr::{self, NonNull};
+use crate::sync::atomic::AtomicPtr;
+use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
+use crate::time::Duration;
+use fortanix_sgx_abi::{EV_UNPARK, WAIT_INDEFINITE};
+
+// The TCS structure must be page-aligned (this is checked by EENTER), so these cannot
+// be valid pointers
+const EMPTY: *mut u8 = ptr::invalid_mut(1);
+const NOTIFIED: *mut u8 = ptr::invalid_mut(2);
+
+pub struct Parker {
+    /// The park state. One of EMPTY, NOTIFIED or a TCS address.
+    /// A state change to NOTIFIED must be done with release ordering
+    /// and be observed with acquire ordering so that operations after
+    /// `thread::park` returns will not occur before the unpark message
+    /// was sent.
+    state: AtomicPtr<u8>,
+}
+
+impl Parker {
+    /// Construct the thread parker. The UNIX parker implementation
+    /// requires this to happen in-place.
+    pub unsafe fn new(parker: *mut Parker) {
+        unsafe { parker.write(Parker::new_internal()) }
+    }
+
+    pub(super) fn new_internal() -> Parker {
+        Parker { state: AtomicPtr::new(EMPTY) }
+    }
+
+    // This implementation doesn't require `unsafe` and `Pin`, but other implementations do.
+    pub unsafe fn park(self: Pin<&Self>) {
+        if self.state.load(Acquire) != NOTIFIED {
+            let mut prev = EMPTY;
+            loop {
+                // Guard against changing TCS addresses by always setting the state to
+                // the current value.
+                let tcs = thread::current().as_ptr();
+                if self.state.compare_exchange(prev, tcs, Relaxed, Acquire).is_ok() {
+                    let event = usercalls::wait(EV_UNPARK, WAIT_INDEFINITE).unwrap();
+                    assert!(event & EV_UNPARK == EV_UNPARK);
+                    prev = tcs;
+                } else {
+                    // The state was definitely changed by another thread at this point.
+                    // The only time this occurs is when the state is changed to NOTIFIED.
+                    // We observed this change with acquire ordering, so we can simply
+                    // change the state to EMPTY with a relaxed store.
+                    break;
+                }
+            }
+        }
+
+        // At this point, the token was definately read with acquire ordering,
+        // so this can be a relaxed store.
+        self.state.store(EMPTY, Relaxed);
+    }
+
+    // This implementation doesn't require `unsafe` and `Pin`, but other implementations do.
+    pub unsafe fn park_timeout(self: Pin<&Self>, dur: Duration) {
+        let timeout = u128::min(dur.as_nanos(), WAIT_INDEFINITE as u128 - 1) as u64;
+        let tcs = thread::current().as_ptr();
+
+        if self.state.load(Acquire) != NOTIFIED {
+            if self.state.compare_exchange(EMPTY, tcs, Relaxed, Acquire).is_ok() {
+                match usercalls::wait(EV_UNPARK, timeout) {
+                    Ok(event) => assert!(event & EV_UNPARK == EV_UNPARK),
+                    Err(e) => {
+                        assert!(matches!(e.kind(), ErrorKind::TimedOut | ErrorKind::WouldBlock))
+                    }
+                }
+
+                // Swap to provide acquire ordering even if the timeout occurred
+                // before the token was set. This situation can result in spurious
+                // wakeups on the next call to `park_timeout`, but it is better to let
+                // those be handled by the user than do some perhaps unnecessary, but
+                // always expensive guarding.
+                self.state.swap(EMPTY, Acquire);
+                return;
+            }
+        }
+
+        // The token was already read with `acquire` ordering, this can be a store.
+        self.state.store(EMPTY, Relaxed);
+    }
+
+    // This implementation doesn't require `Pin`, but other implementations do.
+    pub fn unpark(self: Pin<&Self>) {
+        let state = self.state.swap(NOTIFIED, Release);
+
+        if !matches!(state, EMPTY | NOTIFIED) {
+            // There is a thread waiting, wake it up.
+            let tcs = NonNull::new(state).unwrap();
+            // This will fail if the thread has already terminated or its TCS is destroyed
+            // by the time the signal is sent, but that is fine. If another thread receives
+            // the same TCS, it will receive this notification as a spurious wakeup, but
+            // all users of `wait` should and (internally) do guard against those where
+            // necessary.
+            let _ = usercalls::send(EV_UNPARK, Some(tcs));
+        }
+    }
+}
diff --git a/library/std/src/sys/solid/io.rs b/library/std/src/sys/solid/io.rs
index 9eb17a10daa..a862bb78702 100644
--- a/library/std/src/sys/solid/io.rs
+++ b/library/std/src/sys/solid/io.rs
@@ -75,3 +75,7 @@ impl<'a> IoSliceMut<'a> {
         unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
     }
 }
+
+pub fn is_terminal<T>(_: &T) -> bool {
+    false
+}
diff --git a/library/std/src/sys/solid/os.rs b/library/std/src/sys/solid/os.rs
index 4906c62689d..6135921f0b5 100644
--- a/library/std/src/sys/solid/os.rs
+++ b/library/std/src/sys/solid/os.rs
@@ -1,7 +1,6 @@
 use super::unsupported;
-use crate::convert::TryFrom;
 use crate::error::Error as StdError;
-use crate::ffi::{CStr, CString, OsStr, OsString};
+use crate::ffi::{CStr, OsStr, OsString};
 use crate::fmt;
 use crate::io;
 use crate::os::{
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 37a49f2d78a..fb8d06c6682 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -332,11 +332,23 @@ pub struct FileTimes {
     modified: Option<SystemTime>,
 }
 
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+#[derive(Copy, Clone, Eq, Debug)]
 pub struct FileType {
     mode: mode_t,
 }
 
+impl PartialEq for FileType {
+    fn eq(&self, other: &Self) -> bool {
+        self.masked() == other.masked()
+    }
+}
+
+impl core::hash::Hash for FileType {
+    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
+        self.masked().hash(state);
+    }
+}
+
 #[derive(Debug)]
 pub struct DirBuilder {
     mode: mode_t,
@@ -548,7 +560,11 @@ impl FileType {
     }
 
     pub fn is(&self, mode: mode_t) -> bool {
-        self.mode & libc::S_IFMT == mode
+        self.masked() == mode
+    }
+
+    fn masked(&self) -> mode_t {
+        self.mode & libc::S_IFMT
     }
 }
 
diff --git a/library/std/src/sys/unix/locks/pthread_condvar.rs b/library/std/src/sys/unix/locks/pthread_condvar.rs
index 1ddb09905db..6be1abc2b08 100644
--- a/library/std/src/sys/unix/locks/pthread_condvar.rs
+++ b/library/std/src/sys/unix/locks/pthread_condvar.rs
@@ -2,6 +2,7 @@ use crate::cell::UnsafeCell;
 use crate::ptr;
 use crate::sync::atomic::{AtomicPtr, Ordering::Relaxed};
 use crate::sys::locks::{pthread_mutex, Mutex};
+use crate::sys::time::TIMESPEC_MAX;
 use crate::sys_common::lazy_box::{LazyBox, LazyInit};
 use crate::time::Duration;
 
@@ -12,13 +13,6 @@ pub struct Condvar {
     mutex: AtomicPtr<libc::pthread_mutex_t>,
 }
 
-const TIMESPEC_MAX: libc::timespec =
-    libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 };
-
-fn saturating_cast_to_time_t(value: u64) -> libc::time_t {
-    if value > <libc::time_t>::MAX as u64 { <libc::time_t>::MAX } else { value as libc::time_t }
-}
-
 #[inline]
 fn raw(c: &Condvar) -> *mut libc::pthread_cond_t {
     c.inner.0.get()
@@ -133,26 +127,15 @@ impl Condvar {
         target_os = "horizon"
     )))]
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
-        use crate::mem;
+        use crate::sys::time::Timespec;
 
         let mutex = pthread_mutex::raw(mutex);
         self.verify(mutex);
 
-        let mut now: libc::timespec = mem::zeroed();
-        let r = libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut now);
-        assert_eq!(r, 0);
-
-        // Nanosecond calculations can't overflow because both values are below 1e9.
-        let nsec = dur.subsec_nanos() + now.tv_nsec as u32;
-
-        let sec = saturating_cast_to_time_t(dur.as_secs())
-            .checked_add((nsec / 1_000_000_000) as libc::time_t)
-            .and_then(|s| s.checked_add(now.tv_sec));
-        let nsec = nsec % 1_000_000_000;
-
-        let timeout =
-            sec.map(|s| libc::timespec { tv_sec: s, tv_nsec: nsec as _ }).unwrap_or(TIMESPEC_MAX);
-
+        let timeout = Timespec::now(libc::CLOCK_MONOTONIC)
+            .checked_add_duration(&dur)
+            .and_then(|t| t.to_timespec())
+            .unwrap_or(TIMESPEC_MAX);
         let r = libc::pthread_cond_timedwait(raw(self), mutex, &timeout);
         assert!(r == libc::ETIMEDOUT || r == 0);
         r == 0
@@ -169,57 +152,41 @@ impl Condvar {
         target_os = "espidf",
         target_os = "horizon"
     ))]
-    pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool {
+    pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
+        use crate::sys::time::SystemTime;
         use crate::time::Instant;
 
         let mutex = pthread_mutex::raw(mutex);
         self.verify(mutex);
 
-        // 1000 years
-        let max_dur = Duration::from_secs(1000 * 365 * 86400);
-
-        if dur > max_dur {
-            // OSX implementation of `pthread_cond_timedwait` is buggy
-            // with super long durations. When duration is greater than
-            // 0x100_0000_0000_0000 seconds, `pthread_cond_timedwait`
-            // in macOS Sierra return error 316.
-            //
-            // This program demonstrates the issue:
-            // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c
-            //
-            // To work around this issue, and possible bugs of other OSes, timeout
-            // is clamped to 1000 years, which is allowable per the API of `wait_timeout`
-            // because of spurious wakeups.
-
-            dur = max_dur;
-        }
-
-        // First, figure out what time it currently is, in both system and
-        // stable time.  pthread_cond_timedwait uses system time, but we want to
-        // report timeout based on stable time.
-        let mut sys_now = libc::timeval { tv_sec: 0, tv_usec: 0 };
-        let stable_now = Instant::now();
-        let r = libc::gettimeofday(&mut sys_now, ptr::null_mut());
-        assert_eq!(r, 0, "unexpected error: {:?}", crate::io::Error::last_os_error());
-
-        let nsec = dur.subsec_nanos() as libc::c_long + (sys_now.tv_usec * 1000) as libc::c_long;
-        let extra = (nsec / 1_000_000_000) as libc::time_t;
-        let nsec = nsec % 1_000_000_000;
-        let seconds = saturating_cast_to_time_t(dur.as_secs());
-
-        let timeout = sys_now
-            .tv_sec
-            .checked_add(extra)
-            .and_then(|s| s.checked_add(seconds))
-            .map(|s| libc::timespec { tv_sec: s, tv_nsec: nsec })
+        // OSX implementation of `pthread_cond_timedwait` is buggy
+        // with super long durations. When duration is greater than
+        // 0x100_0000_0000_0000 seconds, `pthread_cond_timedwait`
+        // in macOS Sierra returns error 316.
+        //
+        // This program demonstrates the issue:
+        // https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c
+        //
+        // To work around this issue, and possible bugs of other OSes, timeout
+        // is clamped to 1000 years, which is allowable per the API of `wait_timeout`
+        // because of spurious wakeups.
+        let dur = Duration::min(dur, Duration::from_secs(1000 * 365 * 86400));
+
+        // pthread_cond_timedwait uses system time, but we want to report timeout
+        // based on stable time.
+        let now = Instant::now();
+
+        let timeout = SystemTime::now()
+            .t
+            .checked_add_duration(&dur)
+            .and_then(|t| t.to_timespec())
             .unwrap_or(TIMESPEC_MAX);
 
-        // And wait!
         let r = libc::pthread_cond_timedwait(raw(self), mutex, &timeout);
         debug_assert!(r == libc::ETIMEDOUT || r == 0);
 
         // ETIMEDOUT is not a totally reliable method of determining timeout due
         // to clock shifts, so do the check ourselves
-        stable_now.elapsed() < dur
+        now.elapsed() < dur
     }
 }
diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs
index c1d30dd9d52..6ecf5bdcf86 100644
--- a/library/std/src/sys/unix/thread.rs
+++ b/library/std/src/sys/unix/thread.rs
@@ -136,7 +136,7 @@ impl Thread {
 
         unsafe {
             // Available since glibc 2.12, musl 1.1.16, and uClibc 1.0.20.
-            let name = truncate_cstr(name, TASK_COMM_LEN);
+            let name = truncate_cstr::<{ TASK_COMM_LEN }>(name);
             let res = libc::pthread_setname_np(libc::pthread_self(), name.as_ptr());
             // We have no good way of propagating errors here, but in debug-builds let's check that this actually worked.
             debug_assert_eq!(res, 0);
@@ -153,7 +153,7 @@ impl Thread {
     #[cfg(any(target_os = "macos", target_os = "ios", target_os = "watchos"))]
     pub fn set_name(name: &CStr) {
         unsafe {
-            let name = truncate_cstr(name, libc::MAXTHREADNAMESIZE);
+            let name = truncate_cstr::<{ libc::MAXTHREADNAMESIZE }>(name);
             let res = libc::pthread_setname_np(name.as_ptr());
             // We have no good way of propagating errors here, but in debug-builds let's check that this actually worked.
             debug_assert_eq!(res, 0);
@@ -285,17 +285,12 @@ impl Drop for Thread {
 }
 
 #[cfg(any(target_os = "linux", target_os = "macos", target_os = "ios", target_os = "watchos"))]
-fn truncate_cstr(cstr: &CStr, max_with_nul: usize) -> crate::borrow::Cow<'_, CStr> {
-    use crate::{borrow::Cow, ffi::CString};
-
-    if cstr.to_bytes_with_nul().len() > max_with_nul {
-        let bytes = cstr.to_bytes()[..max_with_nul - 1].to_vec();
-        // SAFETY: the non-nul bytes came straight from a CStr.
-        // (CString will add the terminating nul.)
-        Cow::Owned(unsafe { CString::from_vec_unchecked(bytes) })
-    } else {
-        Cow::Borrowed(cstr)
+fn truncate_cstr<const MAX_WITH_NUL: usize>(cstr: &CStr) -> [libc::c_char; MAX_WITH_NUL] {
+    let mut result = [0; MAX_WITH_NUL];
+    for (src, dst) in cstr.to_bytes().iter().zip(&mut result[..MAX_WITH_NUL - 1]) {
+        *dst = *src as libc::c_char;
     }
+    result
 }
 
 pub fn available_parallelism() -> io::Result<NonZeroUsize> {
diff --git a/library/std/src/sys/unix/thread_parker/pthread.rs b/library/std/src/sys/unix/thread_parker/pthread.rs
index 3dfc0026ed1..c400c771567 100644
--- a/library/std/src/sys/unix/thread_parker/pthread.rs
+++ b/library/std/src/sys/unix/thread_parker/pthread.rs
@@ -6,6 +6,7 @@ use crate::pin::Pin;
 use crate::ptr::addr_of_mut;
 use crate::sync::atomic::AtomicUsize;
 use crate::sync::atomic::Ordering::SeqCst;
+use crate::sys::time::TIMESPEC_MAX;
 use crate::time::Duration;
 
 const EMPTY: usize = 0;
@@ -32,9 +33,6 @@ unsafe fn wait(cond: *mut libc::pthread_cond_t, lock: *mut libc::pthread_mutex_t
     debug_assert_eq!(r, 0);
 }
 
-const TIMESPEC_MAX: libc::timespec =
-    libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 };
-
 unsafe fn wait_timeout(
     cond: *mut libc::pthread_cond_t,
     lock: *mut libc::pthread_mutex_t,
diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs
index d5abd9b581c..2daad981b73 100644
--- a/library/std/src/sys/unix/time.rs
+++ b/library/std/src/sys/unix/time.rs
@@ -5,6 +5,9 @@ pub use self::inner::Instant;
 
 const NSEC_PER_SEC: u64 = 1_000_000_000;
 pub const UNIX_EPOCH: SystemTime = SystemTime { t: Timespec::zero() };
+#[allow(dead_code)] // Used for pthread condvar timeouts
+pub const TIMESPEC_MAX: libc::timespec =
+    libc::timespec { tv_sec: <libc::time_t>::MAX, tv_nsec: 1_000_000_000 - 1 };
 
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 #[repr(transparent)]
diff --git a/library/std/src/sys_common/thread_parker/mod.rs b/library/std/src/sys_common/thread_parker/mod.rs
index f86a9a555d3..08a2bdd8229 100644
--- a/library/std/src/sys_common/thread_parker/mod.rs
+++ b/library/std/src/sys_common/thread_parker/mod.rs
@@ -16,6 +16,8 @@ cfg_if::cfg_if! {
         pub use wait_flag::Parker;
     } else if #[cfg(any(windows, target_family = "unix"))] {
         pub use crate::sys::thread_parker::Parker;
+    } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] {
+        pub use crate::sys::thread_parker::Parker;
     } else {
         mod generic;
         pub use generic::Parker;
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index d8c15c76e2d..960fbdf7538 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -3,6 +3,9 @@
 //! This module implements parsing `config.toml` configuration files to tweak
 //! how the build runs.
 
+#[cfg(test)]
+mod tests;
+
 use std::cell::{Cell, RefCell};
 use std::cmp;
 use std::collections::{HashMap, HashSet};
@@ -696,7 +699,7 @@ define_config! {
     }
 }
 
-#[derive(Deserialize)]
+#[derive(Debug, Deserialize)]
 #[serde(untagged)]
 enum StringOrBool {
     String(String),
@@ -822,6 +825,29 @@ impl Config {
     }
 
     pub fn parse(args: &[String]) -> Config {
+        #[cfg(test)]
+        let get_toml = |_: &_| TomlConfig::default();
+        #[cfg(not(test))]
+        let get_toml = |file: &Path| {
+            let contents =
+                t!(fs::read_to_string(file), format!("config file {} not found", file.display()));
+            // Deserialize to Value and then TomlConfig to prevent the Deserialize impl of
+            // TomlConfig and sub types to be monomorphized 5x by toml.
+            match toml::from_str(&contents)
+                .and_then(|table: toml::Value| TomlConfig::deserialize(table))
+            {
+                Ok(table) => table,
+                Err(err) => {
+                    eprintln!("failed to parse TOML configuration '{}': {}", file.display(), err);
+                    crate::detail_exit(2);
+                }
+            }
+        };
+
+        Self::parse_inner(args, get_toml)
+    }
+
+    fn parse_inner<'a>(args: &[String], get_toml: impl 'a + Fn(&Path) -> TomlConfig) -> Config {
         let flags = Flags::parse(&args);
         let mut config = Config::default_opts();
 
@@ -907,25 +933,6 @@ impl Config {
 
         config.stage0_metadata = t!(serde_json::from_slice::<Stage0Metadata>(&stage0_json));
 
-        #[cfg(test)]
-        let get_toml = |_| TomlConfig::default();
-        #[cfg(not(test))]
-        let get_toml = |file: &Path| {
-            let contents =
-                t!(fs::read_to_string(file), format!("config file {} not found", file.display()));
-            // Deserialize to Value and then TomlConfig to prevent the Deserialize impl of
-            // TomlConfig and sub types to be monomorphized 5x by toml.
-            match toml::from_str(&contents)
-                .and_then(|table: toml::Value| TomlConfig::deserialize(table))
-            {
-                Ok(table) => table,
-                Err(err) => {
-                    eprintln!("failed to parse TOML configuration '{}': {}", file.display(), err);
-                    crate::detail_exit(2);
-                }
-            }
-        };
-
         // Read from `--config`, then `RUST_BOOTSTRAP_CONFIG`, then `./config.toml`, then `config.toml` in the root directory.
         let toml_path = flags
             .config
@@ -1063,6 +1070,79 @@ impl Config {
         let mut optimize = None;
         let mut ignore_git = None;
 
+        if let Some(rust) = toml.rust {
+            debug = rust.debug;
+            debug_assertions = rust.debug_assertions;
+            debug_assertions_std = rust.debug_assertions_std;
+            overflow_checks = rust.overflow_checks;
+            overflow_checks_std = rust.overflow_checks_std;
+            debug_logging = rust.debug_logging;
+            debuginfo_level = rust.debuginfo_level;
+            debuginfo_level_rustc = rust.debuginfo_level_rustc;
+            debuginfo_level_std = rust.debuginfo_level_std;
+            debuginfo_level_tools = rust.debuginfo_level_tools;
+            debuginfo_level_tests = rust.debuginfo_level_tests;
+            config.rust_split_debuginfo = rust
+                .split_debuginfo
+                .as_deref()
+                .map(SplitDebuginfo::from_str)
+                .map(|v| v.expect("invalid value for rust.split_debuginfo"))
+                .unwrap_or(SplitDebuginfo::default_for_platform(&config.build.triple));
+            optimize = rust.optimize;
+            ignore_git = rust.ignore_git;
+            config.rust_new_symbol_mangling = rust.new_symbol_mangling;
+            set(&mut config.rust_optimize_tests, rust.optimize_tests);
+            set(&mut config.codegen_tests, rust.codegen_tests);
+            set(&mut config.rust_rpath, rust.rpath);
+            set(&mut config.jemalloc, rust.jemalloc);
+            set(&mut config.test_compare_mode, rust.test_compare_mode);
+            set(&mut config.backtrace, rust.backtrace);
+            set(&mut config.channel, rust.channel);
+            config.description = rust.description;
+            set(&mut config.rust_dist_src, rust.dist_src);
+            set(&mut config.verbose_tests, rust.verbose_tests);
+            // in the case "false" is set explicitly, do not overwrite the command line args
+            if let Some(true) = rust.incremental {
+                config.incremental = true;
+            }
+            set(&mut config.use_lld, rust.use_lld);
+            set(&mut config.lld_enabled, rust.lld);
+            set(&mut config.llvm_tools_enabled, rust.llvm_tools);
+            config.rustc_parallel = rust.parallel_compiler.unwrap_or(false);
+            config.rustc_default_linker = rust.default_linker;
+            config.musl_root = rust.musl_root.map(PathBuf::from);
+            config.save_toolstates = rust.save_toolstates.map(PathBuf::from);
+            set(&mut config.deny_warnings, flags.deny_warnings.or(rust.deny_warnings));
+            set(&mut config.backtrace_on_ice, rust.backtrace_on_ice);
+            set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir);
+            config.rust_thin_lto_import_instr_limit = rust.thin_lto_import_instr_limit;
+            set(&mut config.rust_remap_debuginfo, rust.remap_debuginfo);
+            set(&mut config.control_flow_guard, rust.control_flow_guard);
+            config.llvm_libunwind_default = rust
+                .llvm_libunwind
+                .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));
+
+            if let Some(ref backends) = rust.codegen_backends {
+                config.rust_codegen_backends =
+                    backends.iter().map(|s| INTERNER.intern_str(s)).collect();
+            }
+
+            config.rust_codegen_units = rust.codegen_units.map(threads_from_config);
+            config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config);
+            config.rust_profile_use = flags.rust_profile_use.or(rust.profile_use);
+            config.rust_profile_generate = flags.rust_profile_generate.or(rust.profile_generate);
+            config.download_rustc_commit = config.download_ci_rustc_commit(rust.download_rustc);
+
+            config.rust_lto = rust
+                .lto
+                .as_deref()
+                .map(|value| RustcLto::from_str(value).unwrap())
+                .unwrap_or_default();
+        } else {
+            config.rust_profile_use = flags.rust_profile_use;
+            config.rust_profile_generate = flags.rust_profile_generate;
+        }
+
         if let Some(llvm) = toml.llvm {
             match llvm.ccache {
                 Some(StringOrBool::String(ref s)) => config.ccache = Some(s.to_string()),
@@ -1099,13 +1179,17 @@ impl Config {
             config.llvm_polly = llvm.polly.unwrap_or(false);
             config.llvm_clang = llvm.clang.unwrap_or(false);
             config.llvm_build_config = llvm.build_config.clone().unwrap_or(Default::default());
+
+            let asserts = llvm_assertions.unwrap_or(false);
             config.llvm_from_ci = match llvm.download_ci_llvm {
                 Some(StringOrBool::String(s)) => {
                     assert!(s == "if-available", "unknown option `{}` for download-ci-llvm", s);
-                    crate::native::is_ci_llvm_available(&config, llvm_assertions.unwrap_or(false))
+                    crate::native::is_ci_llvm_available(&config, asserts)
                 }
                 Some(StringOrBool::Bool(b)) => b,
-                None => false,
+                None => {
+                    config.channel == "dev" && crate::native::is_ci_llvm_available(&config, asserts)
+                }
             };
 
             if config.llvm_from_ci {
@@ -1145,79 +1229,9 @@ impl Config {
                 // the link step) with each stage.
                 config.llvm_link_shared.set(Some(true));
             }
-        }
-
-        if let Some(rust) = toml.rust {
-            debug = rust.debug;
-            debug_assertions = rust.debug_assertions;
-            debug_assertions_std = rust.debug_assertions_std;
-            overflow_checks = rust.overflow_checks;
-            overflow_checks_std = rust.overflow_checks_std;
-            debug_logging = rust.debug_logging;
-            debuginfo_level = rust.debuginfo_level;
-            debuginfo_level_rustc = rust.debuginfo_level_rustc;
-            debuginfo_level_std = rust.debuginfo_level_std;
-            debuginfo_level_tools = rust.debuginfo_level_tools;
-            debuginfo_level_tests = rust.debuginfo_level_tests;
-            config.rust_split_debuginfo = rust
-                .split_debuginfo
-                .as_deref()
-                .map(SplitDebuginfo::from_str)
-                .map(|v| v.expect("invalid value for rust.split_debuginfo"))
-                .unwrap_or(SplitDebuginfo::default_for_platform(&config.build.triple));
-            optimize = rust.optimize;
-            ignore_git = rust.ignore_git;
-            config.rust_new_symbol_mangling = rust.new_symbol_mangling;
-            set(&mut config.rust_optimize_tests, rust.optimize_tests);
-            set(&mut config.codegen_tests, rust.codegen_tests);
-            set(&mut config.rust_rpath, rust.rpath);
-            set(&mut config.jemalloc, rust.jemalloc);
-            set(&mut config.test_compare_mode, rust.test_compare_mode);
-            set(&mut config.backtrace, rust.backtrace);
-            set(&mut config.channel, rust.channel);
-            config.description = rust.description;
-            set(&mut config.rust_dist_src, rust.dist_src);
-            set(&mut config.verbose_tests, rust.verbose_tests);
-            // in the case "false" is set explicitly, do not overwrite the command line args
-            if let Some(true) = rust.incremental {
-                config.incremental = true;
-            }
-            set(&mut config.use_lld, rust.use_lld);
-            set(&mut config.lld_enabled, rust.lld);
-            set(&mut config.llvm_tools_enabled, rust.llvm_tools);
-            config.rustc_parallel = rust.parallel_compiler.unwrap_or(false);
-            config.rustc_default_linker = rust.default_linker;
-            config.musl_root = rust.musl_root.map(PathBuf::from);
-            config.save_toolstates = rust.save_toolstates.map(PathBuf::from);
-            set(&mut config.deny_warnings, flags.deny_warnings.or(rust.deny_warnings));
-            set(&mut config.backtrace_on_ice, rust.backtrace_on_ice);
-            set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir);
-            config.rust_thin_lto_import_instr_limit = rust.thin_lto_import_instr_limit;
-            set(&mut config.rust_remap_debuginfo, rust.remap_debuginfo);
-            set(&mut config.control_flow_guard, rust.control_flow_guard);
-            config.llvm_libunwind_default = rust
-                .llvm_libunwind
-                .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));
-
-            if let Some(ref backends) = rust.codegen_backends {
-                config.rust_codegen_backends =
-                    backends.iter().map(|s| INTERNER.intern_str(s)).collect();
-            }
-
-            config.rust_codegen_units = rust.codegen_units.map(threads_from_config);
-            config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config);
-            config.rust_profile_use = flags.rust_profile_use.or(rust.profile_use);
-            config.rust_profile_generate = flags.rust_profile_generate.or(rust.profile_generate);
-            config.download_rustc_commit = config.download_ci_rustc_commit(rust.download_rustc);
-
-            config.rust_lto = rust
-                .lto
-                .as_deref()
-                .map(|value| RustcLto::from_str(value).unwrap())
-                .unwrap_or_default();
         } else {
-            config.rust_profile_use = flags.rust_profile_use;
-            config.rust_profile_generate = flags.rust_profile_generate;
+            config.llvm_from_ci =
+                config.channel == "dev" && crate::native::is_ci_llvm_available(&config, false);
         }
 
         if let Some(t) = toml.target {
diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs
new file mode 100644
index 00000000000..c30c9131745
--- /dev/null
+++ b/src/bootstrap/config/tests.rs
@@ -0,0 +1,24 @@
+use super::{Config, TomlConfig};
+use std::path::Path;
+
+fn toml(config: &str) -> impl '_ + Fn(&Path) -> TomlConfig {
+    |&_| toml::from_str(config).unwrap()
+}
+
+fn parse(config: &str) -> Config {
+    Config::parse_inner(&["check".to_owned(), "--config=/does/not/exist".to_owned()], toml(config))
+}
+
+#[test]
+fn download_ci_llvm() {
+    let parse_llvm = |s| parse(s).llvm_from_ci;
+    let if_available = parse_llvm("llvm.download-ci-llvm = \"if-available\"");
+
+    assert!(parse_llvm("llvm.download-ci-llvm = true"));
+    assert!(!parse_llvm("llvm.download-ci-llvm = false"));
+    assert_eq!(parse_llvm(""), if_available);
+    assert_eq!(parse_llvm("rust.channel = \"dev\""), if_available);
+    assert!(!parse_llvm("rust.channel = \"stable\""));
+}
+
+// FIXME: add test for detecting `src` and `out`
diff --git a/src/bootstrap/defaults/config.user.toml b/src/bootstrap/defaults/config.user.toml
index 6647061d88f..48ae2fe448d 100644
--- a/src/bootstrap/defaults/config.user.toml
+++ b/src/bootstrap/defaults/config.user.toml
@@ -7,3 +7,7 @@ test-stage = 2
 doc-stage = 2
 # When compiling from source, you usually want all tools.
 extended = true
+
+[llvm]
+# Most users installing from source want to build all parts of the project from source, not just rustc itself.
+download-ci-llvm = false
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 3ed53452309..570fe6484e3 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -1639,10 +1639,10 @@ fn chmod(_path: &Path, _perms: u32) {}
 /// If the test is running and code is an error code, it will cause a panic.
 fn detail_exit(code: i32) -> ! {
     // if in test and code is an error code, panic with status code provided
-    if cfg!(test) && code != 0 {
+    if cfg!(test) {
         panic!("status code: {}", code);
     } else {
-        //otherwise,exit with provided status code
+        // otherwise,exit with provided status code
         std::process::exit(code);
     }
 }
diff --git a/src/ci/docker/host-x86_64/dist-powerpc64le-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-powerpc64le-linux/Dockerfile
index 9a290edd561..6b7b32a8bc7 100644
--- a/src/ci/docker/host-x86_64/dist-powerpc64le-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-powerpc64le-linux/Dockerfile
@@ -24,5 +24,5 @@ ENV \
 
 ENV HOSTS=powerpc64le-unknown-linux-gnu
 
-ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs
+ENV RUST_CONFIGURE_ARGS --enable-extended --enable-profiler --disable-docs
 ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile
index c3b47c3510d..06f15bd1211 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile
@@ -25,7 +25,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   zlib1g-dev \
   xz-utils \
   nodejs \
-
+  \
 # Install powershell so we can test x.ps1 on Linux
     apt-transport-https software-properties-common && \
     curl -s "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/packages-microsoft-prod.deb" > packages-microsoft-prod.deb && \
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
index 501d2781646..58c0c5db1a5 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
@@ -15,7 +15,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   sudo \
   xz-utils \
   tidy \
-
+  \
 # Install dependencies for chromium browser
   gconf-service \
   libasound2 \
diff --git a/src/doc/unstable-book/src/compiler-flags/sanitizer.md b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
index b33405f18e9..9bbf9e28fff 100644
--- a/src/doc/unstable-book/src/compiler-flags/sanitizer.md
+++ b/src/doc/unstable-book/src/compiler-flags/sanitizer.md
@@ -14,6 +14,9 @@ This feature allows for use of one of following sanitizers:
   forward-edge control flow protection.
 * [HWAddressSanitizer](#hwaddresssanitizer) a memory error detector similar to
   AddressSanitizer, but based on partial hardware assistance.
+* [KernelControlFlowIntegrity](#kernelcontrolflowintegrity) LLVM Kernel Control
+  Flow Integrity (KCFI) provides forward-edge control flow protection for
+  operating systems kernels.
 * [LeakSanitizer](#leaksanitizer) a run-time memory leak detector.
 * [MemorySanitizer](#memorysanitizer) a detector of uninitialized reads.
 * [MemTagSanitizer](#memtagsanitizer) fast memory error detector based on
@@ -502,6 +505,32 @@ Registers where the failure occurred (pc 0xaaaae0ae4a98):
 SUMMARY: HWAddressSanitizer: tag-mismatch (/.../main+0x54a94)
 ```
 
+# KernelControlFlowIntegrity
+
+The LLVM Kernel Control Flow Integrity (CFI) support to the Rust compiler
+initially provides forward-edge control flow protection for operating systems
+kernels for Rust-compiled code only by aggregating function pointers in groups
+identified by their return and parameter types. (See [LLVM commit cff5bef "KCFI
+sanitizer"](https://github.com/llvm/llvm-project/commit/cff5bef948c91e4919de8a5fb9765e0edc13f3de).)
+
+Forward-edge control flow protection for C or C++ and Rust -compiled code "mixed
+binaries" (i.e., for when C or C++ and Rust -compiled code share the same
+virtual address space) will be provided in later work by defining and using
+compatible type identifiers (see Type metadata in the design document in the
+tracking issue [#89653](https://github.com/rust-lang/rust/issues/89653)).
+
+LLVM KCFI can be enabled with `-Zsanitizer=kcfi`.
+
+LLVM KCFI is supported on the following targets:
+
+* `aarch64-linux-android`
+* `aarch64-unknown-linux-gnu`
+* `x86_64-linux-android`
+* `x86_64-unknown-linux-gnu`
+
+See the [Clang KernelControlFlowIntegrity documentation][clang-kcfi] for more
+details.
+
 # LeakSanitizer
 
 LeakSanitizer is run-time memory leak detector.
@@ -693,6 +722,7 @@ Sanitizers produce symbolized stacktraces when llvm-symbolizer binary is in `PAT
 [clang-asan]: https://clang.llvm.org/docs/AddressSanitizer.html
 [clang-cfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html
 [clang-hwasan]: https://clang.llvm.org/docs/HardwareAssistedAddressSanitizerDesign.html
+[clang-kcfi]: https://clang.llvm.org/docs/ControlFlowIntegrity.html#fsanitize-kcfi
 [clang-lsan]: https://clang.llvm.org/docs/LeakSanitizer.html
 [clang-msan]: https://clang.llvm.org/docs/MemorySanitizer.html
 [clang-scs]: https://clang.llvm.org/docs/ShadowCallStack.html
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index e0cdb86d9d1..56b40d8c66b 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -69,6 +69,8 @@ pub(crate) struct Options {
     pub(crate) input: PathBuf,
     /// The name of the crate being documented.
     pub(crate) crate_name: Option<String>,
+    /// Whether or not this is a bin crate
+    pub(crate) bin_crate: bool,
     /// Whether or not this is a proc-macro crate
     pub(crate) proc_macro_crate: bool,
     /// How to format errors and warnings.
@@ -176,6 +178,7 @@ impl fmt::Debug for Options {
         f.debug_struct("Options")
             .field("input", &self.input)
             .field("crate_name", &self.crate_name)
+            .field("bin_crate", &self.bin_crate)
             .field("proc_macro_crate", &self.proc_macro_crate)
             .field("error_format", &self.error_format)
             .field("libs", &self.libs)
@@ -667,6 +670,7 @@ impl Options {
             None => OutputFormat::default(),
         };
         let crate_name = matches.opt_str("crate-name");
+        let bin_crate = crate_types.contains(&CrateType::Executable);
         let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro);
         let playground_url = matches.opt_str("playground-url");
         let maybe_sysroot = matches.opt_str("sysroot").map(PathBuf::from);
@@ -718,6 +722,7 @@ impl Options {
             rustc_feature::UnstableFeatures::from_environment(crate_name.as_deref());
         let options = Options {
             input,
+            bin_crate,
             proc_macro_crate,
             error_format,
             diagnostic_width,
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 08f8096b07b..36d15ec3b86 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -2957,14 +2957,23 @@ fn render_call_locations(w: &mut Buffer, cx: &mut Context<'_>, item: &clean::Ite
 
     // The call locations are output in sequence, so that sequence needs to be determined.
     // Ideally the most "relevant" examples would be shown first, but there's no general algorithm
-    // for determining relevance. Instead, we prefer the smallest examples being likely the easiest to
-    // understand at a glance.
+    // for determining relevance. We instead proxy relevance with the following heuristics:
+    //   1. Code written to be an example is better than code not written to be an example, e.g.
+    //      a snippet from examples/foo.rs is better than src/lib.rs. We don't know the Cargo
+    //      directory structure in Rustdoc, so we proxy this by prioritizing code that comes from
+    //      a --crate-type bin.
+    //   2. Smaller examples are better than large examples. So we prioritize snippets that have
+    //      the smallest number of lines in their enclosing item.
+    //   3. Finally we sort by the displayed file name, which is arbitrary but prevents the
+    //      ordering of examples from randomly changing between Rustdoc invocations.
     let ordered_locations = {
-        let sort_criterion = |(_, call_data): &(_, &CallData)| {
+        fn sort_criterion<'a>(
+            (_, call_data): &(&PathBuf, &'a CallData),
+        ) -> (bool, u32, &'a String) {
             // Use the first location because that's what the user will see initially
             let (lo, hi) = call_data.locations[0].enclosing_item.byte_span;
-            hi - lo
-        };
+            (!call_data.is_bin, hi - lo, &call_data.display_name)
+        }
 
         let mut locs = call_locations.iter().collect::<Vec<_>>();
         locs.sort_by_key(sort_criterion);
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 11136179607..91162ca4892 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -212,7 +212,7 @@ pre.rust a,
 .mobile-topbar h2 a,
 h1 a,
 .search-results a,
-.item-left .stab,
+.stab,
 .result-name .primitive > i, .result-name .keyword > i {
 	color: var(--main-color);
 }
@@ -630,22 +630,16 @@ pre, .rustdoc.source .example-wrap {
 
 .docblock table {
 	margin: .5em 0;
-	width: calc(100% - 2px);
-	overflow-x: auto;
-	display: block;
 	border-collapse: collapse;
 }
 
-.docblock table td {
+.docblock table td, .docblock table th {
 	padding: .5em;
-	border: 1px dashed var(--border-color);
-	vertical-align: top;
+	border: 1px solid var(--border-color);
 }
 
-.docblock table th {
-	padding: .5em;
-	text-align: left;
-	border: 1px solid var(--border-color);
+.docblock table tbody tr:nth-child(2n) {
+	background: var(--table-alt-row-background-color);
 }
 
 /* Shift "where ..." part of method or fn definition down a line */
@@ -966,22 +960,29 @@ so that we can apply CSS-filters to change the arrow color in themes */
 }
 
 .item-info .stab {
-	width: fit-content;
 	/* This min-height is needed to unify the height of the stab elements because some of them
 	   have emojis.
 	*/
 	min-height: 36px;
 	display: flex;
-	align-items: center;
-	white-space: pre-wrap;
-}
-.stab {
 	padding: 3px;
 	margin-bottom: 5px;
+}
+.item-left .stab {
+	margin-left: 0.3125em;
+}
+.stab {
+	padding: 0 2px;
 	font-size: 0.875rem;
 	font-weight: normal;
 	color: var(--main-color);
 	background-color: var(--stab-background-color);
+	width: fit-content;
+	align-items: center;
+	white-space: pre-wrap;
+	border-radius: 3px;
+	display: inline-flex;
+	vertical-align: text-bottom;
 }
 
 .stab.portability > code {
@@ -994,12 +995,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	margin-right: 0.3rem;
 }
 
-/* This is to prevent the `.stab` elements to overflow the .docblock elements. */
-.docblock .stab {
-	padding: 0 0.125em;
-	margin-bottom: 0;
-}
-
 /* Black one-pixel outline around emoji shapes */
 .emoji {
 	text-shadow:
@@ -1009,16 +1004,6 @@ so that we can apply CSS-filters to change the arrow color in themes */
 		0 -1px 0 black;
 }
 
-.item-left .stab {
-	border-radius: 3px;
-	display: inline-block;
-	line-height: 1.2;
-	margin-bottom: 0;
-	margin-left: 0.3125em;
-	padding: 2px;
-	vertical-align: text-bottom;
-}
-
 .module-item.unstable,
 .import-item.unstable {
 	opacity: 0.65;
@@ -1748,7 +1733,6 @@ in storage.js
 		top: 100px;
 		width: 30px;
 		font-size: 1.5rem;
-		text-align: center;
 		padding: 0;
 		z-index: 10;
 		border-top-right-radius: 3px;
@@ -1813,6 +1797,22 @@ in storage.js
 	}
 }
 
+/* Should have min-width: (N + 1)px where N is the mobile breakpoint above. */
+@media (min-width: 701px) {
+	/* Places file-link for a scraped example on top of the example to save space.
+	   We only do this on large screens so the file-link doesn't overlap too much
+		 with the example's content. */
+	.scraped-example-title {
+		position: absolute;
+		z-index: 10;
+		background: var(--main-background-color);
+		bottom: 8px;
+		right: 5px;
+		padding: 2px 4px;
+		box-shadow: 0 0 4px var(--main-background-color);
+	}
+}
+
 @media print {
 	nav.sidebar, nav.sub, .out-of-band, a.srclink, #copy-path,
 	details.rustdoc-toggle[open] > summary::before, details.rustdoc-toggle > summary::before,
@@ -1899,6 +1899,11 @@ in storage.js
 	border-radius: 50px;
 }
 
+.scraped-example {
+	/* So .scraped-example-title can be positioned absolutely */
+	position: relative;
+}
+
 .scraped-example .code-wrapper {
 	position: relative;
 	display: flex;
@@ -1908,18 +1913,30 @@ in storage.js
 }
 
 .scraped-example:not(.expanded) .code-wrapper {
-	max-height: 240px;
+	/* scrape-examples.js has a constant DEFAULT_MAX_LINES (call it N) for the number
+	 * of lines shown in the un-expanded example code viewer. This pre needs to have
+	 * a max-height equal to line-height * N. The line-height is currently 1.5em,
+	 * and we include additional 10px for padding. */
+	 max-height: calc(1.5em * 5 + 10px);
 }
 
 .scraped-example:not(.expanded) .code-wrapper pre {
 	overflow-y: hidden;
-	max-height: 240px;
 	padding-bottom: 0;
+	/* See above comment, should be the same max-height. */
+	max-height: calc(1.5em * 5 + 10px);
+}
+
+.more-scraped-examples .scraped-example:not(.expanded) .code-wrapper,
+.more-scraped-examples .scraped-example:not(.expanded) .code-wrapper pre {
+	/* See above comment, except this height is based on HIDDEN_MAX_LINES. */
+	max-height: calc(1.5em * 10 + 10px);
 }
 
 .scraped-example .code-wrapper .next,
 .scraped-example .code-wrapper .prev,
 .scraped-example .code-wrapper .expand {
+	color: var(--main-color);
 	position: absolute;
 	top: 0.25em;
 	z-index: 1;
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index 6e0905e730d..eba845bf5a9 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -87,6 +87,7 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 	--crate-search-hover-border: #e0e0e0;
 	--source-sidebar-background-selected: #14191f;
 	--source-sidebar-background-hover: #14191f;
+	--table-alt-row-background-color: #191f26;
 }
 
 h1, h2, h3, h4 {
@@ -159,11 +160,6 @@ body.source .example-wrap pre.rust a {
 	background: #333;
 }
 
-.module-item .stab,
-.import-item .stab {
-	color: #000;
-}
-
 .result-name .primitive > i, .result-name .keyword > i {
 	color: #788797;
 }
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index 334fc3de561..d945e956c53 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -82,6 +82,7 @@
 	--crate-search-hover-border: #2196f3;
 	--source-sidebar-background-selected: #333;
 	--source-sidebar-background-hover: #444;
+	--table-alt-row-background-color: #2A2A2A;
 }
 
 .content .item-info::before { color: #ccc; }
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index 453e7508af4..58955a79316 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -79,6 +79,7 @@
 	--crate-search-hover-border: #717171;
 	--source-sidebar-background-selected: #fff;
 	--source-sidebar-background-hover: #e0e0e0;
+	--table-alt-row-background-color: #F5F5F5;
 }
 
 .content .item-info::before { color: #ccc; }
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 623f46b1096..152116089c7 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -622,7 +622,7 @@ function loadCss(cssUrl) {
         const innerToggle = document.getElementById(toggleAllDocsId);
         removeClass(innerToggle, "will-expand");
         onEachLazy(document.getElementsByClassName("rustdoc-toggle"), e => {
-            if (!hasClass(e, "type-contents-toggle")) {
+            if (!hasClass(e, "type-contents-toggle") && !hasClass(e, "more-examples-toggle")) {
                 e.open = true;
             }
         });
diff --git a/src/librustdoc/html/static/js/scrape-examples.js b/src/librustdoc/html/static/js/scrape-examples.js
index e328e656edd..7a3a9c5f340 100644
--- a/src/librustdoc/html/static/js/scrape-examples.js
+++ b/src/librustdoc/html/static/js/scrape-examples.js
@@ -3,25 +3,33 @@
 "use strict";
 
 (function() {
-    // Number of lines shown when code viewer is not expanded
-    const MAX_LINES = 10;
+    // Number of lines shown when code viewer is not expanded.
+    // DEFAULT is the first example shown by default, while HIDDEN is
+    // the examples hidden beneath the "More examples" toggle.
+    //
+    // NOTE: these values MUST be synchronized with certain rules in rustdoc.css!
+    const DEFAULT_MAX_LINES = 5;
+    const HIDDEN_MAX_LINES = 10;
 
     // Scroll code block to the given code location
-    function scrollToLoc(elt, loc) {
+    function scrollToLoc(elt, loc, isHidden) {
         const lines = elt.querySelector(".src-line-numbers");
         let scrollOffset;
 
         // If the block is greater than the size of the viewer,
         // then scroll to the top of the block. Otherwise scroll
         // to the middle of the block.
-        if (loc[1] - loc[0] > MAX_LINES) {
+        const maxLines = isHidden ? HIDDEN_MAX_LINES : DEFAULT_MAX_LINES;
+        if (loc[1] - loc[0] > maxLines) {
             const line = Math.max(0, loc[0] - 1);
             scrollOffset = lines.children[line].offsetTop;
         } else {
             const wrapper = elt.querySelector(".code-wrapper");
             const halfHeight = wrapper.offsetHeight / 2;
-            const offsetMid = (lines.children[loc[0]].offsetTop
-                             + lines.children[loc[1]].offsetTop) / 2;
+            const offsetTop = lines.children[loc[0]].offsetTop;
+            const lastLine = lines.children[loc[1]];
+            const offsetBot = lastLine.offsetTop + lastLine.offsetHeight;
+            const offsetMid = (offsetTop + offsetBot) / 2;
             scrollOffset = offsetMid - halfHeight;
         }
 
@@ -29,7 +37,7 @@
         elt.querySelector(".rust").scrollTo(0, scrollOffset);
     }
 
-    function updateScrapedExample(example) {
+    function updateScrapedExample(example, isHidden) {
         const locs = JSON.parse(example.attributes.getNamedItem("data-locs").textContent);
         let locIndex = 0;
         const highlights = Array.prototype.slice.call(example.querySelectorAll(".highlight"));
@@ -40,7 +48,7 @@
             const onChangeLoc = changeIndex => {
                 removeClass(highlights[locIndex], "focus");
                 changeIndex();
-                scrollToLoc(example, locs[locIndex][0]);
+                scrollToLoc(example, locs[locIndex][0], isHidden);
                 addClass(highlights[locIndex], "focus");
 
                 const url = locs[locIndex][1];
@@ -70,7 +78,7 @@
             expandButton.addEventListener("click", () => {
                 if (hasClass(example, "expanded")) {
                     removeClass(example, "expanded");
-                    scrollToLoc(example, locs[0][0]);
+                    scrollToLoc(example, locs[0][0], isHidden);
                 } else {
                     addClass(example, "expanded");
                 }
@@ -78,11 +86,11 @@
         }
 
         // Start with the first example in view
-        scrollToLoc(example, locs[0][0]);
+        scrollToLoc(example, locs[0][0], isHidden);
     }
 
     const firstExamples = document.querySelectorAll(".scraped-example-list > .scraped-example");
-    onEachLazy(firstExamples, updateScrapedExample);
+    onEachLazy(firstExamples, el => updateScrapedExample(el, false));
     onEachLazy(document.querySelectorAll(".more-examples-toggle"), toggle => {
         // Allow users to click the left border of the <details> section to close it,
         // since the section can be large and finding the [+] button is annoying.
@@ -99,7 +107,7 @@
             // depends on offsetHeight, a property that requires an element to be visible to
             // compute correctly.
             setTimeout(() => {
-                onEachLazy(moreExamples, updateScrapedExample);
+                onEachLazy(moreExamples, el => updateScrapedExample(el, true));
             });
         }, {once: true});
     });
diff --git a/src/librustdoc/html/static/scrape-examples-help.md b/src/librustdoc/html/static/scrape-examples-help.md
index 035b2e18b00..002d19ec9b6 100644
--- a/src/librustdoc/html/static/scrape-examples-help.md
+++ b/src/librustdoc/html/static/scrape-examples-help.md
@@ -1,4 +1,4 @@
-Rustdoc will automatically scrape examples of documented items from the `examples/` directory of a project. These examples will be included within the generated documentation for that item. For example, if your library contains a public function:
+Rustdoc will automatically scrape examples of documented items from a project's source code. These examples will be included within the generated documentation for that item. For example, if your library contains a public function:
 
 ```rust
 // src/lib.rs
@@ -16,6 +16,7 @@ fn main() {
 
 Then this code snippet will be included in the documentation for `a_func`.
 
+
 ## How to read scraped examples
 
 Scraped examples are shown as blocks of code from a given file. The relevant item will be highlighted. If the file is larger than a couple lines, only a small window will be shown which you can expand by clicking &varr; in the top-right. If a file contains multiple instances of an item, you can use the &pr; and &sc; buttons to toggle through each instance.
@@ -25,7 +26,7 @@ If there is more than one file that contains examples, then you should click "Mo
 
 ## How Rustdoc scrapes examples
 
-When you run `cargo doc`, Rustdoc will analyze all the crates that match Cargo's `--examples` filter for instances of items that occur in the crates being documented. Then Rustdoc will include the source code of these instances in the generated documentation.
+When you run `cargo doc -Zunstable-options -Zrustdoc-scrape-examples`, Rustdoc will analyze all the documented crates for uses of documented items. Then Rustdoc will include the source code of these instances in the generated documentation.
 
 Rustdoc has a few techniques to ensure this doesn't overwhelm documentation readers, and that it doesn't blow up the page size:
 
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 6d34f484754..ef1d7da5a34 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -674,7 +674,7 @@ type MainResult = Result<(), ErrorGuaranteed>;
 
 fn wrap_return(diag: &rustc_errors::Handler, res: Result<(), String>) -> MainResult {
     match res {
-        Ok(()) => Ok(()),
+        Ok(()) => diag.has_errors().map_or(Ok(()), Err),
         Err(err) => {
             let reported = diag.struct_err(&err).emit();
             Err(reported)
@@ -689,7 +689,7 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>(
     tcx: TyCtxt<'tcx>,
 ) -> MainResult {
     match formats::run_format::<T>(krate, renderopts, cache, tcx) {
-        Ok(_) => Ok(()),
+        Ok(_) => tcx.sess.has_errors().map_or(Ok(()), Err),
         Err(e) => {
             let mut msg =
                 tcx.sess.struct_err(&format!("couldn't generate documentation: {}", e.error));
@@ -774,6 +774,7 @@ fn main_args(at_args: &[String]) -> MainResult {
     let output_format = options.output_format;
     let externs = options.externs.clone();
     let scrape_examples_options = options.scrape_examples_options.clone();
+    let bin_crate = options.bin_crate;
 
     let config = core::create_config(options);
 
@@ -832,7 +833,14 @@ fn main_args(at_args: &[String]) -> MainResult {
                 info!("finished with rustc");
 
                 if let Some(options) = scrape_examples_options {
-                    return scrape_examples::run(krate, render_opts, cache, tcx, options);
+                    return scrape_examples::run(
+                        krate,
+                        render_opts,
+                        cache,
+                        tcx,
+                        options,
+                        bin_crate,
+                    );
                 }
 
                 cache.crate_version = crate_version;
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index dfa6ba38b88..f2ee99cd9d4 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -110,6 +110,7 @@ pub(crate) struct CallData {
     pub(crate) url: String,
     pub(crate) display_name: String,
     pub(crate) edition: Edition,
+    pub(crate) is_bin: bool,
 }
 
 pub(crate) type FnCallLocations = FxHashMap<PathBuf, CallData>;
@@ -122,6 +123,7 @@ struct FindCalls<'a, 'tcx> {
     cx: Context<'tcx>,
     target_crates: Vec<CrateNum>,
     calls: &'a mut AllCallLocations,
+    bin_crate: bool,
 }
 
 impl<'a, 'tcx> Visitor<'tcx> for FindCalls<'a, 'tcx>
@@ -245,7 +247,9 @@ where
                 let mk_call_data = || {
                     let display_name = file_path.display().to_string();
                     let edition = call_span.edition();
-                    CallData { locations: Vec::new(), url, display_name, edition }
+                    let is_bin = self.bin_crate;
+
+                    CallData { locations: Vec::new(), url, display_name, edition, is_bin }
                 };
 
                 let fn_key = tcx.def_path_hash(*def_id);
@@ -274,6 +278,7 @@ pub(crate) fn run(
     cache: formats::cache::Cache,
     tcx: TyCtxt<'_>,
     options: ScrapeExamplesOptions,
+    bin_crate: bool,
 ) -> interface::Result<()> {
     let inner = move || -> Result<(), String> {
         // Generates source files for examples
@@ -300,7 +305,8 @@ pub(crate) fn run(
 
         // Run call-finder on all items
         let mut calls = FxHashMap::default();
-        let mut finder = FindCalls { calls: &mut calls, tcx, map: tcx.hir(), cx, target_crates };
+        let mut finder =
+            FindCalls { calls: &mut calls, tcx, map: tcx.hir(), cx, target_crates, bin_crate };
         tcx.hir().visit_all_item_likes_in_crate(&mut finder);
 
         // The visitor might have found a type error, which we need to
diff --git a/src/test/codegen/catch-unwind.rs b/src/test/codegen/catch-unwind.rs
index 3ea3a24bfae..b90ef104ce7 100644
--- a/src/test/codegen/catch-unwind.rs
+++ b/src/test/codegen/catch-unwind.rs
@@ -8,6 +8,8 @@
 // On riscv the closure is another function, placed before fn foo so CHECK can't
 // find it
 // ignore-riscv64 FIXME
+// On s390x the closure is also in another function
+// ignore-s390x FIXME
 
 #![crate_type = "lib"]
 #![feature(c_unwind)]
diff --git a/src/test/codegen/issue-105386-ub-in-debuginfo.rs b/src/test/codegen/issue-105386-ub-in-debuginfo.rs
new file mode 100644
index 00000000000..d54ac9e33bc
--- /dev/null
+++ b/src/test/codegen/issue-105386-ub-in-debuginfo.rs
@@ -0,0 +1,22 @@
+// compile-flags: --crate-type=lib -O -Cdebuginfo=2 -Cno-prepopulate-passes
+// min-llvm-version: 15.0 # this test uses opaque pointer notation
+#![feature(stmt_expr_attributes)]
+
+pub struct S([usize; 8]);
+
+#[no_mangle]
+pub fn outer_function(x: S, y: S) -> usize {
+    (#[inline(always)]|| {
+        let _z = x;
+        y.0[0]
+    })()
+}
+
+// Check that we do not attempt to load from the spilled arg before it is assigned to
+// when generating debuginfo.
+// CHECK-LABEL: @outer_function
+// CHECK: [[spill:%.*]] = alloca %"[closure@{{.*.rs}}:9:23: 9:25]"
+// CHECK-NOT: [[ptr_tmp:%.*]] = getelementptr inbounds %"[closure@{{.*.rs}}:9:23: 9:25]", ptr [[spill]]
+// CHECK-NOT: [[load:%.*]] = load ptr, ptr
+// CHECK: call void @llvm.lifetime.start{{.*}}({{.*}}, ptr [[spill]])
+// CHECK: call void @llvm.memcpy{{.*}}(ptr {{align .*}} [[spill]], ptr {{align .*}} %x
diff --git a/src/test/codegen/remap_path_prefix/main.rs b/src/test/codegen/remap_path_prefix/main.rs
index 9bef743ddcb..78ebbccfce1 100644
--- a/src/test/codegen/remap_path_prefix/main.rs
+++ b/src/test/codegen/remap_path_prefix/main.rs
@@ -12,7 +12,7 @@ mod aux_mod;
 include!("aux_mod.rs");
 
 // Here we check that the expansion of the file!() macro is mapped.
-// CHECK: @alloc2 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>, align 1
+// CHECK: @alloc2 = private unnamed_addr constant <{ [34 x i8] }> <{ [34 x i8] c"/the/src/remap_path_prefix/main.rs" }>
 pub static FILE_PATH: &'static str = file!();
 
 fn main() {
diff --git a/src/test/codegen/repr-transparent-aggregates-1.rs b/src/test/codegen/repr-transparent-aggregates-1.rs
index 9d18c5f03c6..f733de12b35 100644
--- a/src/test/codegen/repr-transparent-aggregates-1.rs
+++ b/src/test/codegen/repr-transparent-aggregates-1.rs
@@ -8,6 +8,7 @@
 // ignore-powerpc
 // ignore-powerpc64
 // ignore-riscv64 see codegen/riscv-abi
+// ignore-s390x
 // ignore-windows
 // See repr-transparent.rs
 
diff --git a/src/test/codegen/repr-transparent.rs b/src/test/codegen/repr-transparent.rs
index c68ba8460cb..4f2313ce47a 100644
--- a/src/test/codegen/repr-transparent.rs
+++ b/src/test/codegen/repr-transparent.rs
@@ -2,6 +2,7 @@
 
 // ignore-riscv64 riscv64 has an i128 type used with test_Vector
 // see codegen/riscv-abi for riscv functiona call tests
+// ignore-s390x s390x with default march passes vector types per reference
 
 #![crate_type="lib"]
 #![feature(repr_simd, transparent_unions)]
diff --git a/src/test/codegen/sanitizer-kcfi-add-kcfi-flag.rs b/src/test/codegen/sanitizer-kcfi-add-kcfi-flag.rs
new file mode 100644
index 00000000000..c2eb852aec3
--- /dev/null
+++ b/src/test/codegen/sanitizer-kcfi-add-kcfi-flag.rs
@@ -0,0 +1,11 @@
+// Verifies that "kcfi" module flag is added.
+//
+// needs-sanitizer-kcfi
+// compile-flags: -Ctarget-feature=-crt-static -Zsanitizer=kcfi
+
+#![crate_type="lib"]
+
+pub fn foo() {
+}
+
+// CHECK: !{{[0-9]+}} = !{i32 4, !"kcfi", i32 1}
diff --git a/src/test/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs b/src/test/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs
new file mode 100644
index 00000000000..0afd9727517
--- /dev/null
+++ b/src/test/codegen/sanitizer-kcfi-emit-kcfi-operand-bundle-itanium-cxx-abi.rs
@@ -0,0 +1,47 @@
+// Verifies that KCFI type metadata for functions are emitted.
+//
+// revisions: aarch64 x86_64
+// [aarch64] compile-flags: --target aarch64-unknown-none
+// [aarch64] needs-llvm-components: aarch64
+// [x86_64] compile-flags: --target x86_64-unknown-none
+// [x86_64] needs-llvm-components:
+// compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi
+
+#![crate_type="lib"]
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang="sized"]
+trait Sized { }
+#[lang="copy"]
+trait Copy { }
+
+impl Copy for i32 {}
+
+pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}foo
+    // FIXME(rcvalle): Change <unknown kind #36> to !kcfi_type when Rust is updated to LLVM 16
+    // CHECK-SAME: {{.*}}!<unknown kind #36> ![[TYPE1:[0-9]+]]
+    // CHECK: call i32 %f(i32 %arg){{.*}}[ "kcfi"(i32 -1666898348) ]
+    f(arg)
+}
+
+pub fn bar(f: fn(i32, i32) -> i32, arg1: i32, arg2: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}bar
+    // FIXME(rcvalle): Change <unknown kind #36> to !kcfi_type when Rust is updated to LLVM 16
+    // CHECK-SAME: {{.*}}!<unknown kind #36> ![[TYPE2:[0-9]+]]
+    // CHECK: call i32 %f(i32 %arg1, i32 %arg2){{.*}}[ "kcfi"(i32 -1789026986) ]
+    f(arg1, arg2)
+}
+
+pub fn baz(f: fn(i32, i32, i32) -> i32, arg1: i32, arg2: i32, arg3: i32) -> i32 {
+    // CHECK-LABEL: define{{.*}}baz
+    // FIXME(rcvalle): Change <unknown kind #36> to !kcfi_type when Rust is updated to LLVM 16
+    // CHECK-SAME: {{.*}}!<unknown kind #36> ![[TYPE3:[0-9]+]]
+    // CHECK: call i32 %f(i32 %arg1, i32 %arg2, i32 %arg3){{.*}}[ "kcfi"(i32 1248878270) ]
+    f(arg1, arg2, arg3)
+}
+
+// CHECK: ![[TYPE1]] = !{i32 653723426}
+// CHECK: ![[TYPE2]] = !{i32 412174924}
+// CHECK: ![[TYPE3]] = !{i32 -636668840}
diff --git a/src/test/codegen/uninit-consts.rs b/src/test/codegen/uninit-consts.rs
index 4c07740b356..98a6761f8ab 100644
--- a/src/test/codegen/uninit-consts.rs
+++ b/src/test/codegen/uninit-consts.rs
@@ -14,7 +14,7 @@ pub struct PartiallyUninit {
 
 // CHECK: [[FULLY_UNINIT:@[0-9]+]] = private unnamed_addr constant <{ [10 x i8] }> undef
 
-// CHECK: [[PARTIALLY_UNINIT:@[0-9]+]] = private unnamed_addr constant <{ [4 x i8], [12 x i8] }> <{ [4 x i8] c"\EF\BE\AD\DE", [12 x i8] undef }>, align 4
+// CHECK: [[PARTIALLY_UNINIT:@[0-9]+]] = private unnamed_addr constant <{ [4 x i8], [12 x i8] }> <{ [4 x i8] c"{{\\EF\\BE\\AD\\DE|\\DE\\AD\\BE\\EF}}", [12 x i8] undef }>, align 4
 
 // This shouldn't contain undef, since it contains more chunks
 // than the default value of uninit_const_chunk_threshold.
diff --git a/src/test/mir-opt/76803_regression.encode.SimplifyBranchSame.diff b/src/test/mir-opt/76803_regression.encode.SimplifyBranchSame.diff
index 57e298625f9..9780332d8bf 100644
--- a/src/test/mir-opt/76803_regression.encode.SimplifyBranchSame.diff
+++ b/src/test/mir-opt/76803_regression.encode.SimplifyBranchSame.diff
@@ -8,7 +8,7 @@
   
       bb0: {
           _2 = discriminant(_1);           // scope 0 at $DIR/76803_regression.rs:+1:11: +1:12
-          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/76803_regression.rs:+1:5: +1:12
+          switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/76803_regression.rs:+1:5: +1:12
       }
   
       bb1: {
diff --git a/src/test/mir-opt/bool_compare.opt1.InstCombine.diff b/src/test/mir-opt/bool_compare.opt1.InstCombine.diff
index 9c5a9fa9abb..0af5d82d315 100644
--- a/src/test/mir-opt/bool_compare.opt1.InstCombine.diff
+++ b/src/test/mir-opt/bool_compare.opt1.InstCombine.diff
@@ -14,7 +14,7 @@
 -         _2 = Ne(move _3, const true);    // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
 +         _2 = Not(move _3);               // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
           StorageDead(_3);                 // scope 0 at $DIR/bool_compare.rs:+1:16: +1:17
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
+          switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
       }
   
       bb1: {
diff --git a/src/test/mir-opt/bool_compare.opt2.InstCombine.diff b/src/test/mir-opt/bool_compare.opt2.InstCombine.diff
index 58c52c4b7d7..f5d1febd991 100644
--- a/src/test/mir-opt/bool_compare.opt2.InstCombine.diff
+++ b/src/test/mir-opt/bool_compare.opt2.InstCombine.diff
@@ -14,7 +14,7 @@
 -         _2 = Ne(const true, move _3);    // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
 +         _2 = Not(move _3);               // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
           StorageDead(_3);                 // scope 0 at $DIR/bool_compare.rs:+1:16: +1:17
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
+          switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:17
       }
   
       bb1: {
diff --git a/src/test/mir-opt/bool_compare.opt3.InstCombine.diff b/src/test/mir-opt/bool_compare.opt3.InstCombine.diff
index 676428c95c1..e7432adac7d 100644
--- a/src/test/mir-opt/bool_compare.opt3.InstCombine.diff
+++ b/src/test/mir-opt/bool_compare.opt3.InstCombine.diff
@@ -14,7 +14,7 @@
 -         _2 = Eq(move _3, const false);   // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
 +         _2 = Not(move _3);               // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
           StorageDead(_3);                 // scope 0 at $DIR/bool_compare.rs:+1:17: +1:18
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
+          switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
       }
   
       bb1: {
diff --git a/src/test/mir-opt/bool_compare.opt4.InstCombine.diff b/src/test/mir-opt/bool_compare.opt4.InstCombine.diff
index addfcd769a5..6b3e27772f7 100644
--- a/src/test/mir-opt/bool_compare.opt4.InstCombine.diff
+++ b/src/test/mir-opt/bool_compare.opt4.InstCombine.diff
@@ -14,7 +14,7 @@
 -         _2 = Eq(const false, move _3);   // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
 +         _2 = Not(move _3);               // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
           StorageDead(_3);                 // scope 0 at $DIR/bool_compare.rs:+1:17: +1:18
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
+          switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/bool_compare.rs:+1:8: +1:18
       }
   
       bb1: {
diff --git a/src/test/mir-opt/building/issue_101867.main.built.after.mir b/src/test/mir-opt/building/issue_101867.main.built.after.mir
index 0ebd840cf2d..628a33f1020 100644
--- a/src/test/mir-opt/building/issue_101867.main.built.after.mir
+++ b/src/test/mir-opt/building/issue_101867.main.built.after.mir
@@ -27,7 +27,7 @@ fn main() -> () {
         StorageLive(_5);                 // scope 1 at $DIR/issue_101867.rs:+2:14: +2:15
         FakeRead(ForMatchedPlace(None), _1); // scope 1 at $DIR/issue_101867.rs:+2:19: +2:20
         _6 = discriminant(_1);           // scope 1 at $DIR/issue_101867.rs:+2:19: +2:20
-        switchInt(move _6) -> [1_isize: bb4, otherwise: bb3]; // scope 1 at $DIR/issue_101867.rs:+2:9: +2:16
+        switchInt(move _6) -> [1: bb4, otherwise: bb3]; // scope 1 at $DIR/issue_101867.rs:+2:9: +2:16
     }
 
     bb1: {
diff --git a/src/test/mir-opt/building/issue_49232.main.built.after.mir b/src/test/mir-opt/building/issue_49232.main.built.after.mir
index 9182bcaa21f..de5e4c0f6ed 100644
--- a/src/test/mir-opt/building/issue_49232.main.built.after.mir
+++ b/src/test/mir-opt/building/issue_49232.main.built.after.mir
@@ -25,7 +25,7 @@ fn main() -> () {
         StorageLive(_3);                 // scope 0 at $DIR/issue_49232.rs:+3:19: +3:23
         _3 = const true;                 // scope 0 at $DIR/issue_49232.rs:+3:19: +3:23
         FakeRead(ForMatchedPlace(None), _3); // scope 0 at $DIR/issue_49232.rs:+3:19: +3:23
-        switchInt(_3) -> [false: bb3, otherwise: bb4]; // scope 0 at $DIR/issue_49232.rs:+3:13: +3:23
+        switchInt(_3) -> [0: bb3, otherwise: bb4]; // scope 0 at $DIR/issue_49232.rs:+3:13: +3:23
     }
 
     bb3: {
diff --git a/src/test/mir-opt/building/match_false_edges.full_tested_match.built.after.mir b/src/test/mir-opt/building/match_false_edges.full_tested_match.built.after.mir
index 9a190c3d60e..cb36bc64da6 100644
--- a/src/test/mir-opt/building/match_false_edges.full_tested_match.built.after.mir
+++ b/src/test/mir-opt/building/match_false_edges.full_tested_match.built.after.mir
@@ -28,7 +28,7 @@ fn full_tested_match() -> () {
         _2 = Option::<i32>::Some(const 42_i32); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:27
         FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:27
         _3 = discriminant(_2);           // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:27
-        switchInt(move _3) -> [0_isize: bb1, 1_isize: bb2, otherwise: bb4]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:27
+        switchInt(move _3) -> [0: bb1, 1: bb2, otherwise: bb4]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:27
     }
 
     bb1: {
@@ -60,7 +60,7 @@ fn full_tested_match() -> () {
     }
 
     bb6: {
-        switchInt(move _7) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/match_false_edges.rs:+2:20: +2:27
+        switchInt(move _7) -> [0: bb8, otherwise: bb7]; // scope 0 at $DIR/match_false_edges.rs:+2:20: +2:27
     }
 
     bb7: {
diff --git a/src/test/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir b/src/test/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir
index 1c9953e7efc..7f8755faac6 100644
--- a/src/test/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir
+++ b/src/test/mir-opt/building/match_false_edges.full_tested_match2.built.after.mir
@@ -28,7 +28,7 @@ fn full_tested_match2() -> () {
         _2 = Option::<i32>::Some(const 42_i32); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:27
         FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:27
         _3 = discriminant(_2);           // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:27
-        switchInt(move _3) -> [0_isize: bb1, 1_isize: bb2, otherwise: bb4]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:27
+        switchInt(move _3) -> [0: bb1, 1: bb2, otherwise: bb4]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:27
     }
 
     bb1: {
@@ -66,7 +66,7 @@ fn full_tested_match2() -> () {
     }
 
     bb6: {
-        switchInt(move _7) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/match_false_edges.rs:+2:20: +2:27
+        switchInt(move _7) -> [0: bb8, otherwise: bb7]; // scope 0 at $DIR/match_false_edges.rs:+2:20: +2:27
     }
 
     bb7: {
diff --git a/src/test/mir-opt/building/match_false_edges.main.built.after.mir b/src/test/mir-opt/building/match_false_edges.main.built.after.mir
index 08c67d39d78..e8b93f4371e 100644
--- a/src/test/mir-opt/building/match_false_edges.main.built.after.mir
+++ b/src/test/mir-opt/building/match_false_edges.main.built.after.mir
@@ -39,7 +39,7 @@ fn main() -> () {
         _2 = Option::<i32>::Some(const 1_i32); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:26
         FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:26
         _4 = discriminant(_2);           // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:26
-        switchInt(move _4) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:26
+        switchInt(move _4) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:26
     }
 
     bb1: {
@@ -56,7 +56,7 @@ fn main() -> () {
 
     bb4: {
         _3 = discriminant(_2);           // scope 0 at $DIR/match_false_edges.rs:+1:19: +1:26
-        switchInt(move _3) -> [1_isize: bb6, otherwise: bb5]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:26
+        switchInt(move _3) -> [1: bb6, otherwise: bb5]; // scope 0 at $DIR/match_false_edges.rs:+1:13: +1:26
     }
 
     bb5: {
@@ -87,7 +87,7 @@ fn main() -> () {
     }
 
     bb9: {
-        switchInt(move _8) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/match_false_edges.rs:+2:21: +2:28
+        switchInt(move _8) -> [0: bb11, otherwise: bb10]; // scope 0 at $DIR/match_false_edges.rs:+2:21: +2:28
     }
 
     bb10: {
@@ -134,7 +134,7 @@ fn main() -> () {
     }
 
     bb15: {
-        switchInt(move _12) -> [false: bb17, otherwise: bb16]; // scope 0 at $DIR/match_false_edges.rs:+4:20: +4:29
+        switchInt(move _12) -> [0: bb17, otherwise: bb16]; // scope 0 at $DIR/match_false_edges.rs:+4:20: +4:29
     }
 
     bb16: {
diff --git a/src/test/mir-opt/building/simple_match.match_bool.built.after.mir b/src/test/mir-opt/building/simple_match.match_bool.built.after.mir
index a4516026c3b..aa2fd46320e 100644
--- a/src/test/mir-opt/building/simple_match.match_bool.built.after.mir
+++ b/src/test/mir-opt/building/simple_match.match_bool.built.after.mir
@@ -6,7 +6,7 @@ fn match_bool(_1: bool) -> usize {
 
     bb0: {
         FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/simple_match.rs:+1:11: +1:12
-        switchInt(_1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/simple_match.rs:+1:5: +1:12
+        switchInt(_1) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/simple_match.rs:+1:5: +1:12
     }
 
     bb1: {
diff --git a/src/test/mir-opt/const_goto.issue_77355_opt.ConstGoto.diff b/src/test/mir-opt/const_goto.issue_77355_opt.ConstGoto.diff
index fade2d0bc6e..a717d1bbd12 100644
--- a/src/test/mir-opt/const_goto.issue_77355_opt.ConstGoto.diff
+++ b/src/test/mir-opt/const_goto.issue_77355_opt.ConstGoto.diff
@@ -11,9 +11,9 @@
       bb0: {
 -         StorageLive(_2);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 -         _3 = discriminant(_1);           // scope 0 at $DIR/const_goto.rs:+1:17: +1:20
--         switchInt(move _3) -> [1_isize: bb2, 2_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+-         switchInt(move _3) -> [1: bb2, 2: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 +         _2 = discriminant(_1);           // scope 0 at $DIR/const_goto.rs:+1:17: +1:20
-+         switchInt(move _2) -> [1_isize: bb2, 2_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         switchInt(move _2) -> [1: bb2, 2: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       }
   
       bb1: {
@@ -29,7 +29,7 @@
 -     }
 - 
 -     bb3: {
--         switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+-         switchInt(move _2) -> [0: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 -     }
 - 
 -     bb4: {
diff --git a/src/test/mir-opt/const_goto_const_eval_fail.f.ConstGoto.diff b/src/test/mir-opt/const_goto_const_eval_fail.f.ConstGoto.diff
index 623297aeba5..24be8c9b868 100644
--- a/src/test/mir-opt/const_goto_const_eval_fail.f.ConstGoto.diff
+++ b/src/test/mir-opt/const_goto_const_eval_fail.f.ConstGoto.diff
@@ -10,7 +10,7 @@
           StorageLive(_1);                 // scope 0 at $DIR/const_goto_const_eval_fail.rs:+1:11: +6:6
           StorageLive(_2);                 // scope 0 at $DIR/const_goto_const_eval_fail.rs:+2:15: +2:16
           _2 = const A;                    // scope 0 at $DIR/const_goto_const_eval_fail.rs:+2:15: +2:16
-          switchInt(_2) -> [1_i32: bb2, 2_i32: bb2, 3_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:+2:9: +2:16
+          switchInt(_2) -> [1: bb2, 2: bb2, 3: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:+2:9: +2:16
       }
   
       bb1: {
@@ -21,11 +21,11 @@
       bb2: {
           _1 = const B;                    // scope 0 at $DIR/const_goto_const_eval_fail.rs:+3:26: +3:27
 -         goto -> bb3;                     // scope 0 at $DIR/const_goto_const_eval_fail.rs:+3:26: +3:27
-+         switchInt(_1) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:+1:5: +6:6
++         switchInt(_1) -> [0: bb4, otherwise: bb3]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:+1:5: +6:6
       }
   
       bb3: {
--         switchInt(_1) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:+1:5: +6:6
+-         switchInt(_1) -> [0: bb5, otherwise: bb4]; // scope 0 at $DIR/const_goto_const_eval_fail.rs:+1:5: +6:6
 -     }
 - 
 -     bb4: {
diff --git a/src/test/mir-opt/const_goto_storage.match_nested_if.ConstGoto.diff b/src/test/mir-opt/const_goto_storage.match_nested_if.ConstGoto.diff
index 81c356cb1db..f5457725943 100644
--- a/src/test/mir-opt/const_goto_storage.match_nested_if.ConstGoto.diff
+++ b/src/test/mir-opt/const_goto_storage.match_nested_if.ConstGoto.diff
@@ -23,10 +23,10 @@
 -         StorageLive(_5);                 // scope 0 at $DIR/const_goto_storage.rs:+2:21: +2:52
 -         StorageLive(_6);                 // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
 -         _6 = const true;                 // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
--         switchInt(move _6) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
+-         switchInt(move _6) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
 +         StorageLive(_2);                 // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
 +         _2 = const true;                 // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
-+         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
++         switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/const_goto_storage.rs:+2:24: +2:28
       }
   
       bb1: {
@@ -41,7 +41,7 @@
 - 
 -     bb3: {
 -         StorageDead(_6);                 // scope 0 at $DIR/const_goto_storage.rs:+2:51: +2:52
--         switchInt(move _5) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/const_goto_storage.rs:+2:21: +2:52
+-         switchInt(move _5) -> [0: bb5, otherwise: bb4]; // scope 0 at $DIR/const_goto_storage.rs:+2:21: +2:52
 -     }
 - 
 -     bb4: {
@@ -56,7 +56,7 @@
 - 
 -     bb6: {
 -         StorageDead(_5);                 // scope 0 at $DIR/const_goto_storage.rs:+2:75: +2:76
--         switchInt(move _4) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/const_goto_storage.rs:+2:18: +2:76
+-         switchInt(move _4) -> [0: bb8, otherwise: bb7]; // scope 0 at $DIR/const_goto_storage.rs:+2:18: +2:76
 -     }
 - 
 -     bb7: {
@@ -70,7 +70,7 @@
 -     }
 - 
 -     bb9: {
--         switchInt(move _3) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/const_goto_storage.rs:+2:15: +6:10
+-         switchInt(move _3) -> [0: bb11, otherwise: bb10]; // scope 0 at $DIR/const_goto_storage.rs:+2:15: +6:10
 -     }
 - 
 -     bb10: {
diff --git a/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff
index 8b3b9d0a4c1..147670f8a91 100644
--- a/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/control_flow_simplification.hello.ConstProp.diff
@@ -9,8 +9,8 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
           _1 = const _;                    // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
--         switchInt(move _1) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
-+         switchInt(const false) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
+-         switchInt(move _1) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
++         switchInt(const false) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/control_flow_simplification.rs:+1:8: +1:21
       }
   
       bb1: {
diff --git a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff
index 6b29bb59c40..b4dccecc672 100644
--- a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff
+++ b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff
@@ -21,13 +21,13 @@
           ((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
           discriminant(_3) = 1;            // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
 -         _4 = discriminant(_3);           // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
--         switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+-         switchInt(move _4) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
 +         _4 = const 1_isize;              // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
-+         switchInt(const 1_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
++         switchInt(const 1_isize) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
       }
   
       bb1: {
-          switchInt(((_3 as Some).0: bool)) -> [false: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+          switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
       }
   
       bb2: {
diff --git a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff
index 6b29bb59c40..b4dccecc672 100644
--- a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff
+++ b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff
@@ -21,13 +21,13 @@
           ((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
           discriminant(_3) = 1;            // scope 2 at $DIR/discriminant.rs:+1:34: +1:44
 -         _4 = discriminant(_3);           // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
--         switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+-         switchInt(move _4) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
 +         _4 = const 1_isize;              // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
-+         switchInt(const 1_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
++         switchInt(const 1_isize) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
       }
   
       bb1: {
-          switchInt(((_3 as Some).0: bool)) -> [false: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
+          switchInt(((_3 as Some).0: bool)) -> [0: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:+1:21: +1:31
       }
   
       bb2: {
diff --git a/src/test/mir-opt/const_prop/switch_int.main.ConstProp.diff b/src/test/mir-opt/const_prop/switch_int.main.ConstProp.diff
index 9d7c2784d8b..ddc1a4493db 100644
--- a/src/test/mir-opt/const_prop/switch_int.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/switch_int.main.ConstProp.diff
@@ -8,8 +8,8 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/switch_int.rs:+1:11: +1:12
           _1 = const 1_i32;                // scope 0 at $DIR/switch_int.rs:+1:11: +1:12
--         switchInt(_1) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12
-+         switchInt(const 1_i32) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12
+-         switchInt(_1) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12
++         switchInt(const 1_i32) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12
       }
   
       bb1: {
diff --git a/src/test/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff b/src/test/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff
index 74f9eafe420..09c47ee6e83 100644
--- a/src/test/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff
+++ b/src/test/mir-opt/const_prop/switch_int.main.SimplifyConstCondition-after-const-prop.diff
@@ -8,7 +8,7 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/switch_int.rs:+1:11: +1:12
           _1 = const 1_i32;                // scope 0 at $DIR/switch_int.rs:+1:11: +1:12
--         switchInt(const 1_i32) -> [1_i32: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12
+-         switchInt(const 1_i32) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/switch_int.rs:+1:5: +1:12
 +         goto -> bb2;                     // scope 0 at $DIR/switch_int.rs:+1:5: +1:12
       }
   
diff --git a/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot b/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot
index fd21b14af25..c4d389b2d76 100644
--- a/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot
+++ b/src/test/mir-opt/coverage_graphviz.main.InstrumentCoverage.0.dot
@@ -7,7 +7,7 @@ digraph Cov_0_3 {
     bcb1__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb1</td></tr><tr><td align="left" balign="left">Expression(bcb0 + bcb3) at 10:5-11:17<br align="left"/>    11:12-11:17: @2.Call: _2 = bar() -&gt; [return: bb3, unwind: bb6]</td></tr><tr><td align="left" balign="left">bb1: FalseUnwind<br align="left"/>bb2: Call</td></tr><tr><td align="left" balign="left">bb3: SwitchInt</td></tr></table>>];
     bcb0__Cov_0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">bcb0</td></tr><tr><td align="left" balign="left"></td></tr><tr><td align="left" balign="left">Counter(bcb0) at 9:1-9:11<br align="left"/>    </td></tr><tr><td align="left" balign="left">bb0: Goto</td></tr></table>>];
     bcb3__Cov_0_3 -> bcb1__Cov_0_3 [label=<>];
-    bcb1__Cov_0_3 -> bcb3__Cov_0_3 [label=<false>];
+    bcb1__Cov_0_3 -> bcb3__Cov_0_3 [label=<0>];
     bcb1__Cov_0_3 -> bcb2__Cov_0_3 [label=<otherwise>];
     bcb0__Cov_0_3 -> bcb1__Cov_0_3 [label=<>];
 }
diff --git a/src/test/mir-opt/dataflow-const-prop/enum.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/enum.main.DataflowConstProp.diff
index 2ced794e628..fce18fae436 100644
--- a/src/test/mir-opt/dataflow-const-prop/enum.main.DataflowConstProp.diff
+++ b/src/test/mir-opt/dataflow-const-prop/enum.main.DataflowConstProp.diff
@@ -28,7 +28,7 @@
           discriminant(_1) = 0;            // scope 0 at $DIR/enum.rs:+1:13: +1:21
           StorageLive(_2);                 // scope 1 at $DIR/enum.rs:+2:9: +2:10
           _3 = discriminant(_1);           // scope 1 at $DIR/enum.rs:+2:19: +2:20
-          switchInt(move _3) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 1 at $DIR/enum.rs:+2:13: +2:20
+          switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 1 at $DIR/enum.rs:+2:13: +2:20
       }
   
       bb1: {
diff --git a/src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff
index 26808c70fbf..32489b4bd6b 100644
--- a/src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff
+++ b/src/test/mir-opt/dataflow-const-prop/if.main.DataflowConstProp.diff
@@ -42,8 +42,8 @@
 +         _4 = const 1_i32;                // scope 1 at $DIR/if.rs:+2:16: +2:17
 +         _3 = const true;                 // scope 1 at $DIR/if.rs:+2:16: +2:22
           StorageDead(_4);                 // scope 1 at $DIR/if.rs:+2:21: +2:22
--         switchInt(move _3) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+2:16: +2:22
-+         switchInt(const true) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+2:16: +2:22
+-         switchInt(move _3) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+2:16: +2:22
++         switchInt(const true) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/if.rs:+2:16: +2:22
       }
   
       bb1: {
@@ -73,8 +73,8 @@
 +         _9 = const 1_i32;                // scope 3 at $DIR/if.rs:+5:16: +5:17
 +         _8 = const true;                 // scope 3 at $DIR/if.rs:+5:16: +5:22
           StorageDead(_9);                 // scope 3 at $DIR/if.rs:+5:21: +5:22
--         switchInt(move _8) -> [false: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+5:16: +5:22
-+         switchInt(const true) -> [false: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+5:16: +5:22
+-         switchInt(move _8) -> [0: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+5:16: +5:22
++         switchInt(const true) -> [0: bb5, otherwise: bb4]; // scope 3 at $DIR/if.rs:+5:16: +5:22
       }
   
       bb4: {
diff --git a/src/test/mir-opt/dataflow-const-prop/issue_81605.f.DataflowConstProp.diff b/src/test/mir-opt/dataflow-const-prop/issue_81605.f.DataflowConstProp.diff
index 881d80f7c03..5a87884977c 100644
--- a/src/test/mir-opt/dataflow-const-prop/issue_81605.f.DataflowConstProp.diff
+++ b/src/test/mir-opt/dataflow-const-prop/issue_81605.f.DataflowConstProp.diff
@@ -10,8 +10,8 @@
           StorageLive(_1);                 // scope 0 at $DIR/issue_81605.rs:+1:9: +1:33
           StorageLive(_2);                 // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16
           _2 = const true;                 // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16
--         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16
-+         switchInt(const true) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16
+-         switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16
++         switchInt(const true) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/issue_81605.rs:+1:12: +1:16
       }
   
       bb1: {
diff --git a/src/test/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff b/src/test/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff
index 61d24c3b517..80f8905adc9 100644
--- a/src/test/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff
+++ b/src/test/mir-opt/dead-store-elimination/cycle.cycle.DeadStoreElimination.diff
@@ -37,8 +37,8 @@
       }
   
       bb2: {
--         switchInt(move _5) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/cycle.rs:+3:11: +3:17
-+         switchInt(move _4) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/cycle.rs:+3:11: +3:17
+-         switchInt(move _5) -> [0: bb4, otherwise: bb3]; // scope 0 at $DIR/cycle.rs:+3:11: +3:17
++         switchInt(move _4) -> [0: bb4, otherwise: bb3]; // scope 0 at $DIR/cycle.rs:+3:11: +3:17
       }
   
       bb3: {
diff --git a/src/test/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff b/src/test/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff
index fb18089e040..210d3849e18 100644
--- a/src/test/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff
+++ b/src/test/mir-opt/deaggregator_test_enum_2.test1.Deaggregator.diff
@@ -12,7 +12,7 @@
       bb0: {
           StorageLive(_3);                 // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
           _3 = _1;                         // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
-          switchInt(move _3) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
+          switchInt(move _3) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/deaggregator_test_enum_2.rs:+1:8: +1:9
       }
   
       bb1: {
diff --git a/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff b/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff
index 995611f0e96..3b1f81175cb 100644
--- a/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff
+++ b/src/test/mir-opt/deduplicate_blocks.is_line_doc_comment_2.DeduplicateBlocks.diff
@@ -28,44 +28,44 @@
           _7 = Len((*_2));                 // scope 0 at $DIR/deduplicate_blocks.rs:+2:9: +2:37
           _8 = const 4_usize;              // scope 0 at $DIR/deduplicate_blocks.rs:+2:9: +2:37
           _9 = Ge(move _7, move _8);       // scope 0 at $DIR/deduplicate_blocks.rs:+2:9: +2:37
-          switchInt(move _9) -> [false: bb6, otherwise: bb2]; // scope 0 at $DIR/deduplicate_blocks.rs:+2:9: +2:37
+          switchInt(move _9) -> [0: bb6, otherwise: bb2]; // scope 0 at $DIR/deduplicate_blocks.rs:+2:9: +2:37
       }
   
       bb2: {
-          switchInt((*_2)[0 of 4]) -> [47_u8: bb3, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
+          switchInt((*_2)[0 of 4]) -> [47: bb3, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
       }
   
       bb3: {
-          switchInt((*_2)[1 of 4]) -> [47_u8: bb4, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
+          switchInt((*_2)[1 of 4]) -> [47: bb4, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
       }
   
       bb4: {
-          switchInt((*_2)[2 of 4]) -> [47_u8: bb5, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
+          switchInt((*_2)[2 of 4]) -> [47: bb5, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
       }
   
       bb5: {
--         switchInt((*_2)[3 of 4]) -> [47_u8: bb11, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
-+         switchInt((*_2)[3 of 4]) -> [47_u8: bb10, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
+-         switchInt((*_2)[3 of 4]) -> [47: bb11, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
++         switchInt((*_2)[3 of 4]) -> [47: bb10, otherwise: bb6]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
       }
   
       bb6: {
           _4 = Len((*_2));                 // scope 0 at $DIR/deduplicate_blocks.rs:+3:9: +3:31
           _5 = const 3_usize;              // scope 0 at $DIR/deduplicate_blocks.rs:+3:9: +3:31
           _6 = Ge(move _4, move _5);       // scope 0 at $DIR/deduplicate_blocks.rs:+3:9: +3:31
-          switchInt(move _6) -> [false: bb10, otherwise: bb7]; // scope 0 at $DIR/deduplicate_blocks.rs:+3:9: +3:31
+          switchInt(move _6) -> [0: bb10, otherwise: bb7]; // scope 0 at $DIR/deduplicate_blocks.rs:+3:9: +3:31
       }
   
       bb7: {
-          switchInt((*_2)[0 of 3]) -> [47_u8: bb8, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
+          switchInt((*_2)[0 of 3]) -> [47: bb8, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
       }
   
       bb8: {
-          switchInt((*_2)[1 of 3]) -> [47_u8: bb9, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
+          switchInt((*_2)[1 of 3]) -> [47: bb9, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
       }
   
       bb9: {
--         switchInt((*_2)[2 of 3]) -> [47_u8: bb12, 33_u8: bb13, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
-+         switchInt((*_2)[2 of 3]) -> [47_u8: bb11, 33_u8: bb11, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
+-         switchInt((*_2)[2 of 3]) -> [47: bb12, 33: bb13, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
++         switchInt((*_2)[2 of 3]) -> [47: bb11, 33: bb11, otherwise: bb10]; // scope 0 at $DIR/deduplicate_blocks.rs:+1:5: +1:23
       }
   
       bb10: {
diff --git a/src/test/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir b/src/test/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir
index 5b185082d4d..9597a0c835f 100644
--- a/src/test/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir
+++ b/src/test/mir-opt/deref-patterns/string.foo.PreCodegen.after.mir
@@ -17,7 +17,7 @@ fn foo(_1: Option<String>) -> i32 {
         _7 = const false;                // scope 0 at $DIR/string.rs:+1:11: +1:12
         _7 = const true;                 // scope 0 at $DIR/string.rs:+1:11: +1:12
         _5 = discriminant(_1);           // scope 0 at $DIR/string.rs:+1:11: +1:12
-        switchInt(move _5) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/string.rs:+1:5: +1:12
+        switchInt(move _5) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/string.rs:+1:5: +1:12
     }
 
     bb1: {
@@ -47,7 +47,7 @@ fn foo(_1: Option<String>) -> i32 {
     }
 
     bb4: {
-        switchInt(move _4) -> [false: bb1, otherwise: bb5]; // scope 0 at $DIR/string.rs:+2:14: +2:17
+        switchInt(move _4) -> [0: bb1, otherwise: bb5]; // scope 0 at $DIR/string.rs:+2:14: +2:17
     }
 
     bb5: {
@@ -69,6 +69,6 @@ fn foo(_1: Option<String>) -> i32 {
     }
 
     bb9: {
-        switchInt(_7) -> [false: bb7, otherwise: bb8]; // scope 0 at $DIR/string.rs:+5:1: +5:2
+        switchInt(_7) -> [0: bb7, otherwise: bb8]; // scope 0 at $DIR/string.rs:+5:1: +5:2
     }
 }
diff --git a/src/test/mir-opt/derefer_complex_case.main.Derefer.diff b/src/test/mir-opt/derefer_complex_case.main.Derefer.diff
index 713d56c3836..fa3eeedc40f 100644
--- a/src/test/mir-opt/derefer_complex_case.main.Derefer.diff
+++ b/src/test/mir-opt/derefer_complex_case.main.Derefer.diff
@@ -62,7 +62,7 @@
       bb3: {
           StorageDead(_8);                 // scope 1 at $DIR/derefer_complex_case.rs:+1:25: +1:26
           _10 = discriminant(_7);          // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26
-          switchInt(move _10) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26
+          switchInt(move _10) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 1 at $DIR/derefer_complex_case.rs:+1:17: +1:26
       }
   
       bb4: {
diff --git a/src/test/mir-opt/derefer_terminator_test.main.Derefer.diff b/src/test/mir-opt/derefer_terminator_test.main.Derefer.diff
index 60f7b9d5607..ab2388d1323 100644
--- a/src/test/mir-opt/derefer_terminator_test.main.Derefer.diff
+++ b/src/test/mir-opt/derefer_terminator_test.main.Derefer.diff
@@ -54,11 +54,11 @@
           _6 = &_7;                        // scope 2 at $DIR/derefer_terminator_test.rs:+3:18: +3:21
           _5 = &_6;                        // scope 2 at $DIR/derefer_terminator_test.rs:+3:17: +3:21
           _4 = &_5;                        // scope 2 at $DIR/derefer_terminator_test.rs:+3:15: +3:22
--         switchInt((*(*(*(*_4))))) -> [false: bb3, otherwise: bb4]; // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
+-         switchInt((*(*(*(*_4))))) -> [0: bb3, otherwise: bb4]; // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
 +         _10 = deref_copy (*_4);          // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
 +         _11 = deref_copy (*_10);         // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
 +         _12 = deref_copy (*_11);         // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
-+         switchInt((*_12)) -> [false: bb3, otherwise: bb4]; // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
++         switchInt((*_12)) -> [0: bb3, otherwise: bb4]; // scope 2 at $DIR/derefer_terminator_test.rs:+3:5: +3:22
       }
   
       bb3: {
diff --git a/src/test/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff b/src/test/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff
index 5fa7013d5ca..9c729663265 100644
--- a/src/test/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff
+++ b/src/test/mir-opt/dest-prop/branch.foo.DestinationPropagation.diff
@@ -37,7 +37,7 @@
       }
   
       bb2: {
-          switchInt(move _3) -> [false: bb4, otherwise: bb3]; // scope 1 at $DIR/branch.rs:+3:16: +3:22
+          switchInt(move _3) -> [0: bb4, otherwise: bb3]; // scope 1 at $DIR/branch.rs:+3:16: +3:22
       }
   
       bb3: {
diff --git a/src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
index 89d8106ae3c..98a02ee38dd 100644
--- a/src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
+++ b/src/test/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
@@ -31,13 +31,13 @@
           StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
           StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
           _7 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
--         switchInt(move _7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+-         switchInt(move _7) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         StorageLive(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         _10 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         _11 = Ne(_7, move _10);          // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         StorageDead(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
-+         switchInt(move _11) -> [false: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
++         switchInt(move _11) -> [0: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
       }
   
       bb1: {
@@ -49,7 +49,7 @@
   
       bb2: {
 -         _6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
--         switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+-         switchInt(move _6) -> [1: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 -     }
 - 
 -     bb3: {
@@ -72,7 +72,7 @@
 + 
 +     bb4: {
 +         StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
-+         switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
++         switchInt(_7) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
       }
   }
   
diff --git a/src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
index 1a9efa93003..aa75c44b809 100644
--- a/src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
+++ b/src/test/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
@@ -32,18 +32,18 @@
           StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
           StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
           _8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
--         switchInt(move _8) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+-         switchInt(move _8) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         _11 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         StorageLive(_12);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         _12 = Ne(_8, move _11);          // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
-+         switchInt(move _12) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
++         switchInt(move _12) -> [0: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
       }
   
       bb1: {
 -         _6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
--         switchInt(move _6) -> [0_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+-         switchInt(move _6) -> [0: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 -     }
 - 
 -     bb2: {
@@ -55,7 +55,7 @@
   
 -     bb3: {
 -         _7 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
--         switchInt(move _7) -> [1_isize: bb4, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+-         switchInt(move _7) -> [1: bb4, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 -     }
 - 
 -     bb4: {
@@ -86,7 +86,7 @@
 + 
 +     bb5: {
 +         StorageDead(_12);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
-+         switchInt(_8) -> [0_isize: bb3, 1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
++         switchInt(_8) -> [0: bb3, 1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
       }
   }
   
diff --git a/src/test/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
index 309a72ae58b..cea6ff7cd05 100644
--- a/src/test/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
+++ b/src/test/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
@@ -31,13 +31,13 @@
           StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
           StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch.rs:+1:16: +1:17
           _7 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
--         switchInt(move _7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+-         switchInt(move _7) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         StorageLive(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         _10 = discriminant((_3.1: std::option::Option<bool>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         StorageLive(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         _11 = Ne(_7, move _10);          // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 +         StorageDead(_10);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
-+         switchInt(move _11) -> [false: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
++         switchInt(move _11) -> [0: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
       }
   
       bb1: {
@@ -49,7 +49,7 @@
   
       bb2: {
 -         _6 = discriminant((_3.1: std::option::Option<bool>)); // scope 0 at $DIR/early_otherwise_branch.rs:+1:11: +1:17
--         switchInt(move _6) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
+-         switchInt(move _6) -> [1: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
 -     }
 - 
 -     bb3: {
@@ -72,7 +72,7 @@
 + 
 +     bb4: {
 +         StorageDead(_11);                // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
-+         switchInt(_7) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
++         switchInt(_7) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch.rs:+1:5: +1:17
       }
   }
   
diff --git a/src/test/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
index 9574f32f7f0..b90d70ce43a 100644
--- a/src/test/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
+++ b/src/test/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
@@ -42,13 +42,13 @@
           StorageDead(_6);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:19: +1:20
           StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:19: +1:20
           _10 = discriminant((_4.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
--         switchInt(move _10) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
+-         switchInt(move _10) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
 +         StorageLive(_14);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
 +         _14 = discriminant((_4.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
 +         StorageLive(_15);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
 +         _15 = Ne(_10, move _14);         // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
 +         StorageDead(_14);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
-+         switchInt(move _15) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
++         switchInt(move _15) -> [0: bb5, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
       }
   
       bb1: {
@@ -61,13 +61,13 @@
   
       bb2: {
 -         _9 = discriminant((_4.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
--         switchInt(move _9) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
+-         switchInt(move _9) -> [1: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
 -     }
 - 
 -     bb3: {
           _8 = discriminant((_4.2: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:11: +1:20
--         switchInt(move _8) -> [1_isize: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
-+         switchInt(move _8) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
+-         switchInt(move _8) -> [1: bb4, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
++         switchInt(move _8) -> [1: bb3, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
       }
   
 -     bb4: {
@@ -94,7 +94,7 @@
 + 
 +     bb5: {
 +         StorageDead(_15);                // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
-+         switchInt(_10) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
++         switchInt(_10) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_3_element_tuple.rs:+1:5: +1:20
       }
   }
   
diff --git a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
index 6bc025bb5b2..9edd1a39f45 100644
--- a/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
+++ b/src/test/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
@@ -80,13 +80,13 @@
           StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:23: +5:24
           _34 = deref_copy (_4.0: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
           _11 = discriminant((*_34));      // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-          switchInt(move _11) -> [0_isize: bb1, 1_isize: bb3, 2_isize: bb4, 3_isize: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
+          switchInt(move _11) -> [0: bb1, 1: bb3, 2: bb4, 3: bb5, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
       }
   
       bb1: {
           _35 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
           _7 = discriminant((*_35));       // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-          switchInt(move _7) -> [0_isize: bb6, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
+          switchInt(move _7) -> [0: bb6, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
       }
   
       bb2: {
@@ -104,19 +104,19 @@
       bb3: {
           _36 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
           _8 = discriminant((*_36));       // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-          switchInt(move _8) -> [1_isize: bb7, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
+          switchInt(move _8) -> [1: bb7, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
       }
   
       bb4: {
           _37 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
           _9 = discriminant((*_37));       // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-          switchInt(move _9) -> [2_isize: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
+          switchInt(move _9) -> [2: bb8, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
       }
   
       bb5: {
           _38 = deref_copy (_4.1: &ViewportPercentageLength); // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
           _10 = discriminant((*_38));      // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:14: +5:24
-          switchInt(move _10) -> [3_isize: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
+          switchInt(move _10) -> [3: bb9, otherwise: bb2]; // scope 0 at $DIR/early_otherwise_branch_68867.rs:+5:8: +5:24
       }
   
       bb6: {
diff --git a/src/test/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
index 321f57951b4..82d8b2fc5a4 100644
--- a/src/test/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
+++ b/src/test/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
@@ -38,12 +38,12 @@
           StorageDead(_5);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:16: +1:17
           StorageDead(_4);                 // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:16: +1:17
           _8 = discriminant((_3.0: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
-          switchInt(move _8) -> [0_isize: bb1, 1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:5: +1:17
+          switchInt(move _8) -> [0: bb1, 1: bb4, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:5: +1:17
       }
   
       bb1: {
           _6 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
-          switchInt(move _6) -> [0_isize: bb2, 1_isize: bb7, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:5: +1:17
+          switchInt(move _6) -> [0: bb2, 1: bb7, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:5: +1:17
       }
   
       bb2: {
@@ -57,7 +57,7 @@
   
       bb4: {
           _7 = discriminant((_3.1: std::option::Option<u32>)); // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:11: +1:17
-          switchInt(move _7) -> [0_isize: bb6, 1_isize: bb5, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:5: +1:17
+          switchInt(move _7) -> [0: bb6, 1: bb5, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_noopt.rs:+1:5: +1:17
       }
   
       bb5: {
diff --git a/src/test/mir-opt/early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff
index 8b556acb2c4..a3fa2529b18 100644
--- a/src/test/mir-opt/early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff
+++ b/src/test/mir-opt/early_otherwise_branch_soundness.no_deref_ptr.EarlyOtherwiseBranch.diff
@@ -14,7 +14,7 @@
   
       bb0: {
           _3 = discriminant(_1);           // scope 0 at $DIR/early_otherwise_branch_soundness.rs:+1:11: +1:12
-          switchInt(move _3) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:+1:5: +1:12
+          switchInt(move _3) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:+1:5: +1:12
       }
   
       bb1: {
@@ -24,7 +24,7 @@
   
       bb2: {
           _4 = discriminant((*_2));        // scope 0 at $DIR/early_otherwise_branch_soundness.rs:+3:26: +3:28
-          switchInt(move _4) -> [1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:+3:20: +3:28
+          switchInt(move _4) -> [1: bb4, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:+3:20: +3:28
       }
   
       bb3: {
diff --git a/src/test/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff b/src/test/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff
index 659aed18f04..6d0224b547f 100644
--- a/src/test/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff
+++ b/src/test/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff
@@ -12,13 +12,13 @@
   
       bb0: {
           _3 = discriminant((*_1));        // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
-          switchInt(move _3) -> [1_isize: bb1, otherwise: bb3]; // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
+          switchInt(move _3) -> [1: bb1, otherwise: bb3]; // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
       }
   
       bb1: {
           _4 = deref_copy (((*_1) as Some).0: &E<'_>); // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
           _2 = discriminant((*_4));        // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
-          switchInt(move _2) -> [1_isize: bb2, otherwise: bb3]; // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
+          switchInt(move _2) -> [1: bb2, otherwise: bb3]; // scope 1 at $DIR/early_otherwise_branch_soundness.rs:+1:12: +1:31
       }
   
       bb2: {
diff --git a/src/test/mir-opt/equal_true.opt.InstCombine.diff b/src/test/mir-opt/equal_true.opt.InstCombine.diff
index 89982308e71..8b542a7c19d 100644
--- a/src/test/mir-opt/equal_true.opt.InstCombine.diff
+++ b/src/test/mir-opt/equal_true.opt.InstCombine.diff
@@ -14,7 +14,7 @@
 -         _2 = Eq(move _3, const true);    // scope 0 at $DIR/equal_true.rs:+1:8: +1:17
 +         _2 = move _3;                    // scope 0 at $DIR/equal_true.rs:+1:8: +1:17
           StorageDead(_3);                 // scope 0 at $DIR/equal_true.rs:+1:16: +1:17
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/equal_true.rs:+1:8: +1:17
+          switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/equal_true.rs:+1:8: +1:17
       }
   
       bb1: {
diff --git a/src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir b/src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir
index 08481777ed4..ab955049965 100644
--- a/src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir
+++ b/src/test/mir-opt/exponential_or.match_tuple.SimplifyCfg-initial.after.mir
@@ -19,7 +19,7 @@ fn match_tuple(_1: (u32, bool, Option<i32>, u32)) -> u32 {
 
     bb0: {
         FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/exponential_or.rs:+1:11: +1:12
-        switchInt((_1.0: u32)) -> [1_u32: bb2, 4_u32: bb2, otherwise: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:15: +2:20
+        switchInt((_1.0: u32)) -> [1: bb2, 4: bb2, otherwise: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:15: +2:20
     }
 
     bb1: {
@@ -29,31 +29,31 @@ fn match_tuple(_1: (u32, bool, Option<i32>, u32)) -> u32 {
 
     bb2: {
         _2 = discriminant((_1.2: std::option::Option<i32>)); // scope 0 at $DIR/exponential_or.rs:+2:37: +2:55
-        switchInt(move _2) -> [0_isize: bb4, 1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:37: +2:55
+        switchInt(move _2) -> [0: bb4, 1: bb3, otherwise: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:37: +2:55
     }
 
     bb3: {
-        switchInt((((_1.2: std::option::Option<i32>) as Some).0: i32)) -> [1_i32: bb4, 8_i32: bb4, otherwise: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:37: +2:55
+        switchInt((((_1.2: std::option::Option<i32>) as Some).0: i32)) -> [1: bb4, 8: bb4, otherwise: bb1]; // scope 0 at $DIR/exponential_or.rs:+2:37: +2:55
     }
 
     bb4: {
         _5 = Le(const 6_u32, (_1.3: u32)); // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67
-        switchInt(move _5) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67
+        switchInt(move _5) -> [0: bb6, otherwise: bb5]; // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67
     }
 
     bb5: {
         _6 = Le((_1.3: u32), const 9_u32); // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67
-        switchInt(move _6) -> [false: bb6, otherwise: bb8]; // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67
+        switchInt(move _6) -> [0: bb6, otherwise: bb8]; // scope 0 at $DIR/exponential_or.rs:+2:62: +2:67
     }
 
     bb6: {
         _3 = Le(const 13_u32, (_1.3: u32)); // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77
-        switchInt(move _3) -> [false: bb1, otherwise: bb7]; // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77
+        switchInt(move _3) -> [0: bb1, otherwise: bb7]; // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77
     }
 
     bb7: {
         _4 = Le((_1.3: u32), const 16_u32); // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77
-        switchInt(move _4) -> [false: bb1, otherwise: bb8]; // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77
+        switchInt(move _4) -> [0: bb1, otherwise: bb8]; // scope 0 at $DIR/exponential_or.rs:+2:70: +2:77
     }
 
     bb8: {
diff --git a/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff b/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
index 6ab63e82e35..c1c2cde71ab 100644
--- a/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
+++ b/src/test/mir-opt/funky_arms.float_to_exponential_common.ConstProp.diff
@@ -47,7 +47,7 @@
       bb1: {
           StorageDead(_5);                 // scope 0 at $DIR/funky_arms.rs:+4:36: +4:37
           StorageLive(_6);                 // scope 1 at $DIR/funky_arms.rs:+8:9: +8:13
-          switchInt(_4) -> [false: bb3, otherwise: bb2]; // scope 1 at $DIR/funky_arms.rs:+8:16: +8:32
+          switchInt(_4) -> [0: bb3, otherwise: bb2]; // scope 1 at $DIR/funky_arms.rs:+8:16: +8:32
       }
   
       bb2: {
@@ -75,7 +75,7 @@
       bb5: {
           StorageDead(_8);                 // scope 3 at $DIR/funky_arms.rs:+13:44: +13:45
           _9 = discriminant(_7);           // scope 3 at $DIR/funky_arms.rs:+13:12: +13:27
-          switchInt(move _9) -> [1_isize: bb6, otherwise: bb8]; // scope 3 at $DIR/funky_arms.rs:+13:12: +13:27
+          switchInt(move _9) -> [1: bb6, otherwise: bb8]; // scope 3 at $DIR/funky_arms.rs:+13:12: +13:27
       }
   
       bb6: {
diff --git a/src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir b/src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir
index c3b08bf0648..a8e090020c3 100644
--- a/src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir
+++ b/src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir
@@ -29,7 +29,7 @@ fn main::{closure#0}(_1: *mut [generator@$DIR/generator_drop_cleanup.rs:10:15: 1
 
     bb0: {
         _8 = discriminant((*_1));        // scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6
-        switchInt(move _8) -> [0_u32: bb7, 3_u32: bb10, otherwise: bb11]; // scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6
+        switchInt(move _8) -> [0: bb7, 3: bb10, otherwise: bb11]; // scope 0 at $DIR/generator_drop_cleanup.rs:+0:15: +3:6
     }
 
     bb1: {
diff --git a/src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir b/src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir
index fee6da2c635..b3d3c768a5d 100644
--- a/src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir
+++ b/src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir
@@ -32,7 +32,7 @@ fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator_tiny.rs:19:16: 19:24
 
     bb0: {
         _11 = discriminant((*(_1.0: &mut [generator@$DIR/generator_tiny.rs:19:16: 19:24]))); // scope 0 at $DIR/generator_tiny.rs:+0:16: +6:6
-        switchInt(move _11) -> [0_u32: bb1, 3_u32: bb5, otherwise: bb6]; // scope 0 at $DIR/generator_tiny.rs:+0:16: +6:6
+        switchInt(move _11) -> [0: bb1, 3: bb5, otherwise: bb6]; // scope 0 at $DIR/generator_tiny.rs:+0:16: +6:6
     }
 
     bb1: {
diff --git a/src/test/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff
index 94180d20343..de4235c9e9e 100644
--- a/src/test/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff
+++ b/src/test/mir-opt/if_condition_int.dont_opt_bool.SimplifyComparisonIntegral.diff
@@ -9,7 +9,7 @@
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
           _2 = _1;                         // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
+          switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
       }
   
       bb1: {
diff --git a/src/test/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff
index b22c7eac622..754c6579af0 100644
--- a/src/test/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff
+++ b/src/test/mir-opt/if_condition_int.dont_opt_floats.SimplifyComparisonIntegral.diff
@@ -13,7 +13,7 @@
           _3 = _1;                         // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
           _2 = Eq(move _3, const -42f32);  // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:18
           StorageDead(_3);                 // scope 0 at $DIR/if_condition_int.rs:+1:17: +1:18
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:18
+          switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:18
       }
   
       bb1: {
diff --git a/src/test/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff
index cc0995f99cf..ff23839e291 100644
--- a/src/test/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff
+++ b/src/test/mir-opt/if_condition_int.dont_remove_comparison.SimplifyComparisonIntegral.diff
@@ -20,10 +20,10 @@
           _3 = _1;                         // scope 0 at $DIR/if_condition_int.rs:+1:13: +1:14
 -         _2 = Eq(move _3, const 17_i8);   // scope 0 at $DIR/if_condition_int.rs:+1:13: +1:20
 -         StorageDead(_3);                 // scope 0 at $DIR/if_condition_int.rs:+1:19: +1:20
--         switchInt(_2) -> [false: bb2, otherwise: bb1]; // scope 1 at $DIR/if_condition_int.rs:+2:5: +2:12
+-         switchInt(_2) -> [0: bb2, otherwise: bb1]; // scope 1 at $DIR/if_condition_int.rs:+2:5: +2:12
 +         _2 = Eq(_3, const 17_i8);        // scope 0 at $DIR/if_condition_int.rs:+1:13: +1:20
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:19: +1:20
-+         switchInt(move _3) -> [17_i8: bb1, otherwise: bb2]; // scope 1 at $DIR/if_condition_int.rs:+2:5: +2:12
++         switchInt(move _3) -> [17: bb1, otherwise: bb2]; // scope 1 at $DIR/if_condition_int.rs:+2:5: +2:12
       }
   
       bb1: {
diff --git a/src/test/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff
index 801ea040203..5964d76a4b9 100644
--- a/src/test/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff
+++ b/src/test/mir-opt/if_condition_int.opt_char.SimplifyComparisonIntegral.diff
@@ -13,10 +13,10 @@
           _3 = _1;                         // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
 -         _2 = Eq(move _3, const 'x');     // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
 -         StorageDead(_3);                 // scope 0 at $DIR/if_condition_int.rs:+1:15: +1:16
--         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
+-         switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:15: +1:16
-+         switchInt(move _3) -> ['x': bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
++         switchInt(move _3) -> [120: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
       }
   
       bb1: {
diff --git a/src/test/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff
index 4297f4d6466..98918cc743c 100644
--- a/src/test/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff
+++ b/src/test/mir-opt/if_condition_int.opt_i8.SimplifyComparisonIntegral.diff
@@ -13,10 +13,10 @@
           _3 = _1;                         // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
 -         _2 = Eq(move _3, const 42_i8);   // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
 -         StorageDead(_3);                 // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15
--         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
+-         switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15
-+         switchInt(move _3) -> [42_i8: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
++         switchInt(move _3) -> [42: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
       }
   
       bb1: {
diff --git a/src/test/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff
index 8fb794abbd4..db38140b8d0 100644
--- a/src/test/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff
+++ b/src/test/mir-opt/if_condition_int.opt_multiple_ifs.SimplifyComparisonIntegral.diff
@@ -15,10 +15,10 @@
           _3 = _1;                         // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
 -         _2 = Eq(move _3, const 42_u32);  // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
 -         StorageDead(_3);                 // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15
--         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
+-         switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15
-+         switchInt(move _3) -> [42_u32: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
++         switchInt(move _3) -> [42: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
       }
   
       bb1: {
@@ -34,10 +34,10 @@
           _5 = _1;                         // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:16
 -         _4 = Ne(move _5, const 21_u32);  // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22
 -         StorageDead(_5);                 // scope 0 at $DIR/if_condition_int.rs:+3:21: +3:22
--         switchInt(move _4) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22
+-         switchInt(move _4) -> [0: bb4, otherwise: bb3]; // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+3:21: +3:22
-+         switchInt(move _5) -> [21_u32: bb4, otherwise: bb3]; // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22
++         switchInt(move _5) -> [21: bb4, otherwise: bb3]; // scope 0 at $DIR/if_condition_int.rs:+3:15: +3:22
       }
   
       bb3: {
diff --git a/src/test/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff
index 992253ea780..1a1ac4caafa 100644
--- a/src/test/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff
+++ b/src/test/mir-opt/if_condition_int.opt_negative.SimplifyComparisonIntegral.diff
@@ -13,10 +13,10 @@
           _3 = _1;                         // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
 -         _2 = Eq(move _3, const -42_i32); // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
 -         StorageDead(_3);                 // scope 0 at $DIR/if_condition_int.rs:+1:15: +1:16
--         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
+-         switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:15: +1:16
-+         switchInt(move _3) -> [-42_i32: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
++         switchInt(move _3) -> [4294967254: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:16
       }
   
       bb1: {
diff --git a/src/test/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff b/src/test/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff
index 7cea9472d3a..fc3f50227dc 100644
--- a/src/test/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff
+++ b/src/test/mir-opt/if_condition_int.opt_u32.SimplifyComparisonIntegral.diff
@@ -13,10 +13,10 @@
           _3 = _1;                         // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:9
 -         _2 = Eq(move _3, const 42_u32);  // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
 -         StorageDead(_3);                 // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15
--         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
+-         switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
 +         nop;                             // scope 0 at $DIR/if_condition_int.rs:+1:14: +1:15
-+         switchInt(move _3) -> [42_u32: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
++         switchInt(move _3) -> [42: bb1, otherwise: bb2]; // scope 0 at $DIR/if_condition_int.rs:+1:8: +1:15
       }
   
       bb1: {
diff --git a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff
index 1e703a8fd2b..b787a19f4b2 100644
--- a/src/test/mir-opt/inline/inline_diverging.g.Inline.diff
+++ b/src/test/mir-opt/inline/inline_diverging.g.Inline.diff
@@ -19,7 +19,7 @@
           _3 = _1;                         // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:9
           _2 = Gt(move _3, const 0_i32);   // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:13
           StorageDead(_3);                 // scope 0 at $DIR/inline_diverging.rs:+1:12: +1:13
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:13
+          switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/inline_diverging.rs:+1:8: +1:13
       }
   
       bb1: {
diff --git a/src/test/mir-opt/inline/inline_generator.main.Inline.diff b/src/test/mir-opt/inline/inline_generator.main.Inline.diff
index 91bff3d3234..bd21405f14b 100644
--- a/src/test/mir-opt/inline/inline_generator.main.Inline.diff
+++ b/src/test/mir-opt/inline/inline_generator.main.Inline.diff
@@ -72,7 +72,7 @@
 +         _7 = const false;                // scope 0 at $DIR/inline_generator.rs:+1:14: +1:46
 +         _10 = deref_copy (_2.0: &mut [generator@$DIR/inline_generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
 +         _9 = discriminant((*_10));       // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
-+         switchInt(move _9) -> [0_u32: bb3, 1_u32: bb8, 3_u32: bb7, otherwise: bb9]; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
++         switchInt(move _9) -> [0: bb3, 1: bb8, 3: bb7, otherwise: bb9]; // scope 6 at $DIR/inline_generator.rs:15:5: 15:41
       }
   
 -     bb3: {
@@ -92,7 +92,7 @@
 + 
 +     bb3: {
 +         StorageLive(_8);                 // scope 6 at $DIR/inline_generator.rs:15:17: 15:39
-+         switchInt(move _7) -> [false: bb5, otherwise: bb4]; // scope 6 at $DIR/inline_generator.rs:15:20: 15:21
++         switchInt(move _7) -> [0: bb5, otherwise: bb4]; // scope 6 at $DIR/inline_generator.rs:15:20: 15:21
 +     }
 + 
 +     bb4: {
diff --git a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
index 75af20d482d..60149ff3606 100644
--- a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
+++ b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
@@ -38,9 +38,7 @@ fn bar() -> bool {
                                          // + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[1])) }
         Retag(_10);                      // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
         _4 = &(*_10);                    // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
-        Retag(_4);                       // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
         _3 = &(*_4);                     // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
-        Retag(_3);                       // scope 1 at $DIR/inline_retag.rs:+2:7: +2:9
         StorageLive(_6);                 // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
         StorageLive(_7);                 // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
         _9 = const _;                    // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
@@ -49,9 +47,7 @@ fn bar() -> bool {
                                          // + literal: Const { ty: &i32, val: Unevaluated(bar, [], Some(promoted[0])) }
         Retag(_9);                       // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
         _7 = &(*_9);                     // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
-        Retag(_7);                       // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
         _6 = &(*_7);                     // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
-        Retag(_6);                       // scope 1 at $DIR/inline_retag.rs:+2:11: +2:14
         Retag(_3);                       // scope 2 at $DIR/inline_retag.rs:16:8: 16:9
         Retag(_6);                       // scope 2 at $DIR/inline_retag.rs:16:17: 16:18
         StorageLive(_11);                // scope 2 at $DIR/inline_retag.rs:17:5: 17:7
diff --git a/src/test/mir-opt/inline/inline_shims.drop.Inline.diff b/src/test/mir-opt/inline/inline_shims.drop.Inline.diff
index 7a54beca233..36ddb189e0d 100644
--- a/src/test/mir-opt/inline/inline_shims.drop.Inline.diff
+++ b/src/test/mir-opt/inline/inline_shims.drop.Inline.diff
@@ -39,7 +39,7 @@
 +         StorageLive(_6);                 // scope 2 at $DIR/inline_shims.rs:+2:14: +2:40
 +         StorageLive(_7);                 // scope 2 at $DIR/inline_shims.rs:+2:14: +2:40
 +         _6 = discriminant((*_5));        // scope 3 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-+         switchInt(move _6) -> [0_isize: bb2, otherwise: bb3]; // scope 3 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
++         switchInt(move _6) -> [0: bb2, otherwise: bb3]; // scope 3 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
       }
   
       bb2: {
diff --git a/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff b/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff
index 81d5528231d..2f6f5f87efc 100644
--- a/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff
+++ b/src/test/mir-opt/instrument_coverage.main.InstrumentCoverage.diff
@@ -26,7 +26,7 @@
       }
   
       bb3: {
-          switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at /the/src/instrument_coverage.rs:+2:12: +2:17
+          switchInt(move _2) -> [0: bb5, otherwise: bb4]; // scope 0 at /the/src/instrument_coverage.rs:+2:12: +2:17
       }
   
       bb4: {
diff --git a/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir b/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir
index 82210081832..b0d5b291b6c 100644
--- a/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir
+++ b/src/test/mir-opt/issue_38669.main.SimplifyCfg-initial.after.mir
@@ -26,7 +26,7 @@ fn main() -> () {
         StorageLive(_3);                 // scope 1 at $DIR/issue_38669.rs:+3:9: +5:10
         StorageLive(_4);                 // scope 1 at $DIR/issue_38669.rs:+3:12: +3:24
         _4 = _1;                         // scope 1 at $DIR/issue_38669.rs:+3:12: +3:24
-        switchInt(move _4) -> [false: bb4, otherwise: bb3]; // scope 1 at $DIR/issue_38669.rs:+3:12: +3:24
+        switchInt(move _4) -> [0: bb4, otherwise: bb3]; // scope 1 at $DIR/issue_38669.rs:+3:12: +3:24
     }
 
     bb3: {
diff --git a/src/test/mir-opt/issue_41110.main.ElaborateDrops.after.mir b/src/test/mir-opt/issue_41110.main.ElaborateDrops.after.mir
index c573ad5a8e4..c2ea3ac502f 100644
--- a/src/test/mir-opt/issue_41110.main.ElaborateDrops.after.mir
+++ b/src/test/mir-opt/issue_41110.main.ElaborateDrops.after.mir
@@ -65,6 +65,6 @@ fn main() -> () {
     }
 
     bb8 (cleanup): {
-        switchInt(_5) -> [false: bb6, otherwise: bb7]; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
+        switchInt(_5) -> [0: bb6, otherwise: bb7]; // scope 0 at $DIR/issue_41110.rs:+1:27: +1:28
     }
 }
diff --git a/src/test/mir-opt/issue_41110.test.ElaborateDrops.after.mir b/src/test/mir-opt/issue_41110.test.ElaborateDrops.after.mir
index 470b0323281..82989c3f071 100644
--- a/src/test/mir-opt/issue_41110.test.ElaborateDrops.after.mir
+++ b/src/test/mir-opt/issue_41110.test.ElaborateDrops.after.mir
@@ -96,6 +96,6 @@ fn test() -> () {
     }
 
     bb14 (cleanup): {
-        switchInt(_6) -> [false: bb10, otherwise: bb13]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
+        switchInt(_6) -> [0: bb10, otherwise: bb13]; // scope 0 at $DIR/issue_41110.rs:+5:1: +5:2
     }
 }
diff --git a/src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir b/src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir
index 73372c97bea..00504273245 100644
--- a/src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir
+++ b/src/test/mir-opt/issue_41888.main.ElaborateDrops.after.mir
@@ -33,7 +33,7 @@ fn main() -> () {
     }
 
     bb1: {
-        switchInt(move _2) -> [false: bb7, otherwise: bb2]; // scope 1 at $DIR/issue_41888.rs:+2:8: +2:14
+        switchInt(move _2) -> [0: bb7, otherwise: bb2]; // scope 1 at $DIR/issue_41888.rs:+2:8: +2:14
     }
 
     bb2: {
@@ -52,7 +52,7 @@ fn main() -> () {
     bb4: {
         StorageDead(_3);                 // scope 1 at $DIR/issue_41888.rs:+3:19: +3:20
         _5 = discriminant(_1);           // scope 2 at $DIR/issue_41888.rs:+4:16: +4:24
-        switchInt(move _5) -> [0_isize: bb5, otherwise: bb6]; // scope 2 at $DIR/issue_41888.rs:+4:16: +4:24
+        switchInt(move _5) -> [0: bb5, otherwise: bb6]; // scope 2 at $DIR/issue_41888.rs:+4:16: +4:24
     }
 
     bb5: {
@@ -134,19 +134,19 @@ fn main() -> () {
 
     bb19: {
         _10 = discriminant(_1);          // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
-        switchInt(move _10) -> [0_isize: bb15, otherwise: bb17]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
+        switchInt(move _10) -> [0: bb15, otherwise: bb17]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
     }
 
     bb20: {
-        switchInt(_7) -> [false: bb15, otherwise: bb19]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
+        switchInt(_7) -> [0: bb15, otherwise: bb19]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
     }
 
     bb21 (cleanup): {
         _11 = discriminant(_1);          // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
-        switchInt(move _11) -> [0_isize: bb16, otherwise: bb18]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
+        switchInt(move _11) -> [0: bb16, otherwise: bb18]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
     }
 
     bb22 (cleanup): {
-        switchInt(_7) -> [false: bb12, otherwise: bb21]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
+        switchInt(_7) -> [0: bb12, otherwise: bb21]; // scope 0 at $DIR/issue_41888.rs:+9:1: +9:2
     }
 }
diff --git a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir
index 6969a66ac19..adfa3a7733b 100644
--- a/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir
+++ b/src/test/mir-opt/issue_62289.test.ElaborateDrops.before.mir
@@ -52,7 +52,7 @@ fn test() -> Option<Box<u32>> {
     bb2: {
         StorageDead(_7);                 // scope 0 at $DIR/issue_62289.rs:+1:19: +1:20
         _8 = discriminant(_6);           // scope 0 at $DIR/issue_62289.rs:+1:15: +1:20
-        switchInt(move _8) -> [0_isize: bb3, 1_isize: bb5, otherwise: bb4]; // scope 0 at $DIR/issue_62289.rs:+1:15: +1:20
+        switchInt(move _8) -> [0: bb3, 1: bb5, otherwise: bb4]; // scope 0 at $DIR/issue_62289.rs:+1:15: +1:20
     }
 
     bb3: {
diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff
index b88cdfcbc96..17b81633991 100644
--- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.diff
@@ -116,7 +116,7 @@
           StorageDead(_17);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _15 = Not(move _16);             // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageDead(_16);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          switchInt(move _15) -> [false: bb5, otherwise: bb4]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          switchInt(move _15) -> [0: bb5, otherwise: bb4]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       }
   
       bb4: {
diff --git a/src/test/mir-opt/issue_99325.main.built.after.mir b/src/test/mir-opt/issue_99325.main.built.after.mir
index 3db40412b2e..3e035c18db8 100644
--- a/src/test/mir-opt/issue_99325.main.built.after.mir
+++ b/src/test/mir-opt/issue_99325.main.built.after.mir
@@ -109,7 +109,7 @@ fn main() -> () {
         StorageDead(_12);                // scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _10 = Not(move _11);             // scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageDead(_11);                // scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        switchInt(move _10) -> [false: bb4, otherwise: bb3]; // scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+        switchInt(move _10) -> [0: bb4, otherwise: bb3]; // scope 1 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
     }
 
     bb3: {
@@ -218,7 +218,7 @@ fn main() -> () {
         StorageDead(_33);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _31 = Not(move _32);             // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageDead(_32);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        switchInt(move _31) -> [false: bb13, otherwise: bb12]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+        switchInt(move _31) -> [0: bb13, otherwise: bb12]; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
     }
 
     bb12: {
diff --git a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
index 5a2f4feff35..e0d6b58f229 100644
--- a/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
+++ b/src/test/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.mir
@@ -47,7 +47,7 @@ fn num_to_digit(_1: char) -> u32 {
 
     bb2: {
         _7 = discriminant(_2);           // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
-        switchInt(move _7) -> [0_isize: bb6, 1_isize: bb8, otherwise: bb7]; // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
+        switchInt(move _7) -> [0: bb6, 1: bb8, otherwise: bb7]; // scope 3 at $SRC_DIR/core/src/option.rs:LL:COL
     }
 
     bb3: {
@@ -66,7 +66,7 @@ fn num_to_digit(_1: char) -> u32 {
         StorageDead(_4);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
         StorageDead(_5);                 // scope 1 at $SRC_DIR/core/src/char/methods.rs:LL:COL
         StorageDead(_3);                 // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23
-        switchInt(move _9) -> [1_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23
+        switchInt(move _9) -> [1: bb1, otherwise: bb3]; // scope 0 at $DIR/issue_59352.rs:+2:8: +2:23
     }
 
     bb6: {
diff --git a/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff b/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
index 87066cc62c0..1c69a6232d6 100644
--- a/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
+++ b/src/test/mir-opt/issues/issue_75439.foo.MatchBranchSimplification.diff
@@ -32,15 +32,15 @@
   
       bb1: {
           StorageDead(_3);                 // scope 2 at $DIR/issue_75439.rs:+2:52: +2:53
-          switchInt(_2[0 of 4]) -> [0_u32: bb2, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
+          switchInt(_2[0 of 4]) -> [0: bb2, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
       }
   
       bb2: {
-          switchInt(_2[1 of 4]) -> [0_u32: bb3, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
+          switchInt(_2[1 of 4]) -> [0: bb3, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
       }
   
       bb3: {
-          switchInt(_2[2 of 4]) -> [0_u32: bb5, 4294901760_u32: bb6, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
+          switchInt(_2[2 of 4]) -> [0: bb5, 4294901760: bb6, otherwise: bb8]; // scope 3 at $DIR/issue_75439.rs:+4:12: +4:30
       }
   
       bb4: {
diff --git a/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir b/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir
index 5981ab885f9..4ee2dae49b3 100644
--- a/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir
+++ b/src/test/mir-opt/loop_test.main.SimplifyCfg-promote-consts.after.mir
@@ -16,7 +16,7 @@ fn main() -> () {
         StorageLive(_1);                 // scope 0 at $DIR/loop_test.rs:+4:5: +6:6
         StorageLive(_2);                 // scope 0 at $DIR/loop_test.rs:+4:8: +4:12
         _2 = const true;                 // scope 0 at $DIR/loop_test.rs:+4:8: +4:12
-        switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/loop_test.rs:+4:8: +4:12
+        switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/loop_test.rs:+4:8: +4:12
     }
 
     bb1: {
diff --git a/src/test/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.diff b/src/test/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.diff
index 049bbeac867..9bc7060e958 100644
--- a/src/test/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.diff
+++ b/src/test/mir-opt/lower_array_len.array_bound.NormalizeArrayLen.diff
@@ -38,7 +38,7 @@
           _3 = Lt(move _4, move _5);       // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
           StorageDead(_5);                 // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
           StorageDead(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
-          switchInt(move _3) -> [false: bb4, otherwise: bb2]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
+          switchInt(move _3) -> [0: bb4, otherwise: bb2]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
       }
   
       bb2: {
diff --git a/src/test/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.diff b/src/test/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.diff
index 40ec01eeb41..cf427cfd1e6 100644
--- a/src/test/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.diff
+++ b/src/test/mir-opt/lower_array_len.array_bound_mut.NormalizeArrayLen.diff
@@ -41,7 +41,7 @@
           _3 = Lt(move _4, move _5);       // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
           StorageDead(_5);                 // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
           StorageDead(_4);                 // scope 0 at $DIR/lower_array_len.rs:+1:26: +1:27
-          switchInt(move _3) -> [false: bb4, otherwise: bb2]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
+          switchInt(move _3) -> [0: bb4, otherwise: bb2]; // scope 0 at $DIR/lower_array_len.rs:+1:8: +1:27
       }
   
       bb2: {
diff --git a/src/test/mir-opt/lower_array_len_e2e.array_bound.PreCodegen.after.mir b/src/test/mir-opt/lower_array_len_e2e.array_bound.PreCodegen.after.mir
index 9b1b07f38fc..701c2ad705a 100644
--- a/src/test/mir-opt/lower_array_len_e2e.array_bound.PreCodegen.after.mir
+++ b/src/test/mir-opt/lower_array_len_e2e.array_bound.PreCodegen.after.mir
@@ -19,7 +19,7 @@ fn array_bound(_1: usize, _2: &[u8; N]) -> u8 {
         _3 = Lt(move _4, move _5);       // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
         StorageDead(_5);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
         StorageDead(_4);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
-        switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
+        switchInt(move _3) -> [0: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
     }
 
     bb1: {
diff --git a/src/test/mir-opt/lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir b/src/test/mir-opt/lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir
index 29e379777b0..0440cfce289 100644
--- a/src/test/mir-opt/lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir
+++ b/src/test/mir-opt/lower_array_len_e2e.array_bound_mut.PreCodegen.after.mir
@@ -22,7 +22,7 @@ fn array_bound_mut(_1: usize, _2: &mut [u8; N]) -> u8 {
         _3 = Lt(move _4, move _5);       // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
         StorageDead(_5);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
         StorageDead(_4);                 // scope 0 at $DIR/lower_array_len_e2e.rs:+1:26: +1:27
-        switchInt(move _3) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
+        switchInt(move _3) -> [0: bb3, otherwise: bb1]; // scope 0 at $DIR/lower_array_len_e2e.rs:+1:8: +1:27
     }
 
     bb1: {
diff --git a/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff b/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff
index 5f5d6e68fdc..2b0370cf358 100644
--- a/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff
+++ b/src/test/mir-opt/lower_slice_len.bound.LowerSliceLenCalls.diff
@@ -33,7 +33,7 @@
           _3 = Lt(move _4, move _5);       // scope 0 at $DIR/lower_slice_len.rs:+1:8: +1:27
           StorageDead(_5);                 // scope 0 at $DIR/lower_slice_len.rs:+1:26: +1:27
           StorageDead(_4);                 // scope 0 at $DIR/lower_slice_len.rs:+1:26: +1:27
-          switchInt(move _3) -> [false: bb4, otherwise: bb2]; // scope 0 at $DIR/lower_slice_len.rs:+1:8: +1:27
+          switchInt(move _3) -> [0: bb4, otherwise: bb2]; // scope 0 at $DIR/lower_slice_len.rs:+1:8: +1:27
       }
   
       bb2: {
diff --git a/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff b/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
index d3db3b18271..84e4d35f908 100644
--- a/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
+++ b/src/test/mir-opt/match_arm_scopes.complicated_match.SimplifyCfg-initial.after-ElaborateDrops.after.diff
@@ -32,18 +32,18 @@
   
       bb0: {
 -         FakeRead(ForMatchedPlace(None), _2); // scope 0 at $DIR/match_arm_scopes.rs:+1:11: +1:16
--         switchInt((_2.0: bool)) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
-+         switchInt((_2.0: bool)) -> [false: bb5, otherwise: bb1]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
+-         switchInt((_2.0: bool)) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
++         switchInt((_2.0: bool)) -> [0: bb5, otherwise: bb1]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
       }
   
       bb1: {
 -         falseEdge -> [real: bb8, imaginary: bb3]; // scope 0 at $DIR/match_arm_scopes.rs:+2:9: +2:22
-+         switchInt((_2.1: bool)) -> [false: bb10, otherwise: bb2]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
++         switchInt((_2.1: bool)) -> [0: bb10, otherwise: bb2]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
       }
   
       bb2: {
--         switchInt((_2.1: bool)) -> [false: bb3, otherwise: bb4]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
-+         switchInt((_2.0: bool)) -> [false: bb3, otherwise: bb17]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
+-         switchInt((_2.1: bool)) -> [0: bb3, otherwise: bb4]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
++         switchInt((_2.0: bool)) -> [0: bb3, otherwise: bb17]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
       }
   
       bb3: {
@@ -51,7 +51,7 @@
 -     }
 - 
 -     bb4: {
--         switchInt((_2.0: bool)) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
+-         switchInt((_2.0: bool)) -> [0: bb6, otherwise: bb5]; // scope 0 at $DIR/match_arm_scopes.rs:+1:5: +1:16
 -     }
 - 
 -     bb5: {
@@ -85,8 +85,8 @@
           StorageLive(_9);                 // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
           StorageLive(_10);                // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
           _10 = _1;                        // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
--         switchInt(move _10) -> [false: bb10, otherwise: bb9]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
-+         switchInt(move _10) -> [false: bb7, otherwise: bb6]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
+-         switchInt(move _10) -> [0: bb10, otherwise: bb9]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
++         switchInt(move _10) -> [0: bb7, otherwise: bb6]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
       }
   
 -     bb9: {
@@ -101,8 +101,8 @@
 -     bb10: {
 +     bb7: {
           _9 = (*_6);                      // scope 0 at $DIR/match_arm_scopes.rs:+2:70: +2:71
--         switchInt(move _9) -> [false: bb12, otherwise: bb11]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
-+         switchInt(move _9) -> [false: bb9, otherwise: bb8]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
+-         switchInt(move _9) -> [0: bb12, otherwise: bb11]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
++         switchInt(move _9) -> [0: bb9, otherwise: bb8]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
       }
   
 -     bb11: {
@@ -142,8 +142,8 @@
           StorageLive(_12);                // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
           StorageLive(_13);                // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
           _13 = _1;                        // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
--         switchInt(move _13) -> [false: bb15, otherwise: bb14]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
-+         switchInt(move _13) -> [false: bb12, otherwise: bb11]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
+-         switchInt(move _13) -> [0: bb15, otherwise: bb14]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
++         switchInt(move _13) -> [0: bb12, otherwise: bb11]; // scope 0 at $DIR/match_arm_scopes.rs:+2:45: +2:49
       }
   
 -     bb14: {
@@ -158,8 +158,8 @@
 -     bb15: {
 +     bb12: {
           _12 = (*_6);                     // scope 0 at $DIR/match_arm_scopes.rs:+2:70: +2:71
--         switchInt(move _12) -> [false: bb17, otherwise: bb16]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
-+         switchInt(move _12) -> [false: bb14, otherwise: bb13]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
+-         switchInt(move _12) -> [0: bb17, otherwise: bb16]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
++         switchInt(move _12) -> [0: bb14, otherwise: bb13]; // scope 0 at $DIR/match_arm_scopes.rs:+2:42: +2:73
       }
   
 -     bb16: {
diff --git a/src/test/mir-opt/match_test.main.SimplifyCfg-initial.after.mir b/src/test/mir-opt/match_test.main.SimplifyCfg-initial.after.mir
index b184ffc404e..d51dbf4258c 100644
--- a/src/test/mir-opt/match_test.main.SimplifyCfg-initial.after.mir
+++ b/src/test/mir-opt/match_test.main.SimplifyCfg-initial.after.mir
@@ -28,12 +28,12 @@ fn main() -> () {
         StorageLive(_3);                 // scope 2 at $DIR/match_test.rs:+6:5: +11:6
         FakeRead(ForMatchedPlace(None), _1); // scope 2 at $DIR/match_test.rs:+6:11: +6:12
         _6 = Le(const 0_i32, _1);        // scope 2 at $DIR/match_test.rs:+7:9: +7:14
-        switchInt(move _6) -> [false: bb4, otherwise: bb1]; // scope 2 at $DIR/match_test.rs:+7:9: +7:14
+        switchInt(move _6) -> [0: bb4, otherwise: bb1]; // scope 2 at $DIR/match_test.rs:+7:9: +7:14
     }
 
     bb1: {
         _7 = Lt(_1, const 10_i32);       // scope 2 at $DIR/match_test.rs:+7:9: +7:14
-        switchInt(move _7) -> [false: bb4, otherwise: bb2]; // scope 2 at $DIR/match_test.rs:+7:9: +7:14
+        switchInt(move _7) -> [0: bb4, otherwise: bb2]; // scope 2 at $DIR/match_test.rs:+7:9: +7:14
     }
 
     bb2: {
@@ -47,12 +47,12 @@ fn main() -> () {
 
     bb4: {
         _4 = Le(const 10_i32, _1);       // scope 2 at $DIR/match_test.rs:+8:9: +8:16
-        switchInt(move _4) -> [false: bb7, otherwise: bb5]; // scope 2 at $DIR/match_test.rs:+8:9: +8:16
+        switchInt(move _4) -> [0: bb7, otherwise: bb5]; // scope 2 at $DIR/match_test.rs:+8:9: +8:16
     }
 
     bb5: {
         _5 = Le(_1, const 20_i32);       // scope 2 at $DIR/match_test.rs:+8:9: +8:16
-        switchInt(move _5) -> [false: bb7, otherwise: bb6]; // scope 2 at $DIR/match_test.rs:+8:9: +8:16
+        switchInt(move _5) -> [0: bb7, otherwise: bb6]; // scope 2 at $DIR/match_test.rs:+8:9: +8:16
     }
 
     bb6: {
@@ -60,7 +60,7 @@ fn main() -> () {
     }
 
     bb7: {
-        switchInt(_1) -> [-1_i32: bb8, otherwise: bb3]; // scope 2 at $DIR/match_test.rs:+6:5: +6:12
+        switchInt(_1) -> [4294967295: bb8, otherwise: bb3]; // scope 2 at $DIR/match_test.rs:+6:5: +6:12
     }
 
     bb8: {
@@ -71,7 +71,7 @@ fn main() -> () {
         _8 = &shallow _1;                // scope 2 at $DIR/match_test.rs:+6:11: +6:12
         StorageLive(_9);                 // scope 2 at $DIR/match_test.rs:+7:18: +7:19
         _9 = _2;                         // scope 2 at $DIR/match_test.rs:+7:18: +7:19
-        switchInt(move _9) -> [false: bb11, otherwise: bb10]; // scope 2 at $DIR/match_test.rs:+7:18: +7:19
+        switchInt(move _9) -> [0: bb11, otherwise: bb10]; // scope 2 at $DIR/match_test.rs:+7:18: +7:19
     }
 
     bb10: {
diff --git a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff
index f9eeb1ea5b9..be91b0bfe68 100644
--- a/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff
+++ b/src/test/mir-opt/matches_reduce_branches.bar.MatchBranchSimplification.diff
@@ -33,7 +33,7 @@
           StorageLive(_4);                 // scope 2 at $DIR/matches_reduce_branches.rs:+3:9: +3:10
           StorageLive(_5);                 // scope 3 at $DIR/matches_reduce_branches.rs:+4:9: +4:10
           StorageLive(_6);                 // scope 4 at $DIR/matches_reduce_branches.rs:+6:5: +21:6
--         switchInt(_1) -> [7_i32: bb2, otherwise: bb1]; // scope 4 at $DIR/matches_reduce_branches.rs:+6:5: +6:12
+-         switchInt(_1) -> [7: bb2, otherwise: bb1]; // scope 4 at $DIR/matches_reduce_branches.rs:+6:5: +6:12
 -     }
 - 
 -     bb1: {
diff --git a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff
index 0b40b3be8bd..aa8092ece66 100644
--- a/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff
+++ b/src/test/mir-opt/matches_reduce_branches.foo.MatchBranchSimplification.diff
@@ -11,12 +11,12 @@
       bb0: {
           StorageLive(_2);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _3 = discriminant(_1);           // scope 0 at $DIR/matches_reduce_branches.rs:+1:17: +1:20
--         switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+-         switchInt(move _3) -> [0: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 +         StorageLive(_4);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 +         _4 = move _3;                    // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 +         _2 = Eq(_4, const 0_isize);      // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 +         StorageDead(_4);                 // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-+         switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
++         switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       }
   
       bb1: {
@@ -30,7 +30,7 @@
 -     }
 - 
 -     bb3: {
--         switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+-         switchInt(move _2) -> [0: bb5, otherwise: bb4]; // scope 0 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
 -     }
 - 
 -     bb4: {
diff --git a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff
index b8c7722cd37..193104dd30e 100644
--- a/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff
+++ b/src/test/mir-opt/matches_reduce_branches.match_nested_if.MatchBranchSimplification.diff
@@ -26,7 +26,7 @@
           StorageLive(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
           StorageLive(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
           _6 = const true;                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
--         switchInt(move _6) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
+-         switchInt(move _6) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
 -     }
 - 
 -     bb1: {
@@ -45,7 +45,7 @@
 +         _5 = Ne(_7, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:+2:45: +2:50
 +         StorageDead(_7);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:24: +2:28
           StorageDead(_6);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:51: +2:52
--         switchInt(move _5) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
+-         switchInt(move _5) -> [0: bb5, otherwise: bb4]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
 -     }
 - 
 -     bb4: {
@@ -64,7 +64,7 @@
 +         _4 = Ne(_8, const false);        // scope 0 at $DIR/matches_reduce_branches.rs:+2:69: +2:74
 +         StorageDead(_8);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:21: +2:52
           StorageDead(_5);                 // scope 0 at $DIR/matches_reduce_branches.rs:+2:75: +2:76
--         switchInt(move _4) -> [false: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
+-         switchInt(move _4) -> [0: bb8, otherwise: bb7]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:18: +2:76
 -     }
 - 
 -     bb7: {
@@ -78,7 +78,7 @@
 -     }
 - 
 -     bb9: {
--         switchInt(move _3) -> [false: bb11, otherwise: bb10]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
+-         switchInt(move _3) -> [0: bb11, otherwise: bb10]; // scope 0 at $DIR/matches_reduce_branches.rs:+2:15: +6:10
 -     }
 - 
 -     bb10: {
diff --git a/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff b/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff
index 1b4dddc1d43..3766d99a43b 100644
--- a/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff
+++ b/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff
@@ -8,7 +8,7 @@
   
       bb0: {
           _2 = discriminant(_1);           // scope 0 at $DIR/matches_u8.rs:+1:11: +1:12
-          switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12
+          switchInt(move _2) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12
       }
   
       bb1: {
diff --git a/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff b/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff
index 6e734852e1a..b5146cd539f 100644
--- a/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff
+++ b/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff
@@ -8,7 +8,7 @@
   
       bb0: {
           _2 = discriminant(_1);           // scope 0 at $DIR/matches_u8.rs:+1:11: +1:12
-          switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12
+          switchInt(move _2) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12
       }
   
       bb1: {
diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
index 3e3fda6141a..8e6564a38b0 100644
--- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
+++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir
@@ -62,7 +62,7 @@ fn main() -> () {
         FakeRead(ForLet(None), _6);      // bb1[4]: scope 2 at $DIR/region_subtyping_basic.rs:+3:9: +3:10
         StorageLive(_7);                 // bb1[5]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
         _7 = const ConstValue(Scalar(0x01): bool); // bb1[6]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
-        switchInt(move _7) -> [ConstValue(Scalar(0x00): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
+        switchInt(move _7) -> [0: bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
     }
 
     bb2: {
diff --git a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
index 39a53702a4c..74d44c6741a 100644
--- a/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
+++ b/src/test/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir
@@ -62,7 +62,7 @@ fn main() -> () {
         FakeRead(ForLet(None), _6);      // bb1[4]: scope 2 at $DIR/region_subtyping_basic.rs:+3:9: +3:10
         StorageLive(_7);                 // bb1[5]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
         _7 = const ConstValue(Scalar(0x01): bool); // bb1[6]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
-        switchInt(move _7) -> [ConstValue(Scalar(0x00): bool): bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
+        switchInt(move _7) -> [0: bb4, otherwise: bb2]; // bb1[7]: scope 3 at $DIR/region_subtyping_basic.rs:+4:8: +4:12
     }
 
     bb2: {
diff --git a/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir
index e708255cea4..69327b7afac 100644
--- a/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/no_drop_for_inactive_variant.unwrap.SimplifyCfg-elaborate-drops.after.mir
@@ -15,7 +15,7 @@ fn unwrap(_1: Option<T>) -> T {
 
     bb0: {
         _2 = discriminant(_1);           // scope 0 at $DIR/no_drop_for_inactive_variant.rs:+1:11: +1:14
-        switchInt(move _2) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/no_drop_for_inactive_variant.rs:+1:5: +1:14
+        switchInt(move _2) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/no_drop_for_inactive_variant.rs:+1:5: +1:14
     }
 
     bb1: {
diff --git a/src/test/mir-opt/not_equal_false.opt.InstCombine.diff b/src/test/mir-opt/not_equal_false.opt.InstCombine.diff
index 5009d090668..b558c35ac1e 100644
--- a/src/test/mir-opt/not_equal_false.opt.InstCombine.diff
+++ b/src/test/mir-opt/not_equal_false.opt.InstCombine.diff
@@ -14,7 +14,7 @@
 -         _2 = Ne(move _3, const false);   // scope 0 at $DIR/not_equal_false.rs:+1:8: +1:18
 +         _2 = move _3;                    // scope 0 at $DIR/not_equal_false.rs:+1:8: +1:18
           StorageDead(_3);                 // scope 0 at $DIR/not_equal_false.rs:+1:17: +1:18
-          switchInt(move _2) -> [false: bb2, otherwise: bb1]; // scope 0 at $DIR/not_equal_false.rs:+1:8: +1:18
+          switchInt(move _2) -> [0: bb2, otherwise: bb1]; // scope 0 at $DIR/not_equal_false.rs:+1:8: +1:18
       }
   
       bb1: {
diff --git a/src/test/mir-opt/remove_fake_borrows.match_guard.CleanupNonCodegenStatements.diff b/src/test/mir-opt/remove_fake_borrows.match_guard.CleanupNonCodegenStatements.diff
index 243a54b6a84..bb5920b28ca 100644
--- a/src/test/mir-opt/remove_fake_borrows.match_guard.CleanupNonCodegenStatements.diff
+++ b/src/test/mir-opt/remove_fake_borrows.match_guard.CleanupNonCodegenStatements.diff
@@ -16,7 +16,7 @@
 -         FakeRead(ForMatchedPlace(None), _1); // scope 0 at $DIR/remove_fake_borrows.rs:+1:11: +1:12
 +         nop;                             // scope 0 at $DIR/remove_fake_borrows.rs:+1:11: +1:12
           _3 = discriminant(_1);           // scope 0 at $DIR/remove_fake_borrows.rs:+1:11: +1:12
-          switchInt(move _3) -> [1_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/remove_fake_borrows.rs:+1:5: +1:12
+          switchInt(move _3) -> [1: bb2, otherwise: bb1]; // scope 0 at $DIR/remove_fake_borrows.rs:+1:5: +1:12
       }
   
       bb1: {
@@ -25,7 +25,7 @@
       }
   
       bb2: {
-          switchInt((*(*((_1 as Some).0: &&i32)))) -> [0_i32: bb3, otherwise: bb1]; // scope 0 at $DIR/remove_fake_borrows.rs:+1:5: +1:12
+          switchInt((*(*((_1 as Some).0: &&i32)))) -> [0: bb3, otherwise: bb1]; // scope 0 at $DIR/remove_fake_borrows.rs:+1:5: +1:12
       }
   
       bb3: {
@@ -43,7 +43,7 @@
 +         nop;                             // scope 0 at $DIR/remove_fake_borrows.rs:+1:11: +1:12
           StorageLive(_8);                 // scope 0 at $DIR/remove_fake_borrows.rs:+2:20: +2:21
           _8 = _2;                         // scope 0 at $DIR/remove_fake_borrows.rs:+2:20: +2:21
-          switchInt(move _8) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/remove_fake_borrows.rs:+2:20: +2:21
+          switchInt(move _8) -> [0: bb6, otherwise: bb5]; // scope 0 at $DIR/remove_fake_borrows.rs:+2:20: +2:21
       }
   
       bb5: {
diff --git a/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff b/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
index 188aa556490..ed1d0b87f60 100644
--- a/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
+++ b/src/test/mir-opt/remove_storage_markers.main.RemoveStorageMarkers.diff
@@ -63,7 +63,7 @@
       bb3: {
 -         StorageDead(_8);                 // scope 2 at $DIR/remove_storage_markers.rs:+2:18: +2:19
           _10 = discriminant(_7);          // scope 2 at $DIR/remove_storage_markers.rs:+2:14: +2:19
-          switchInt(move _10) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 2 at $DIR/remove_storage_markers.rs:+2:14: +2:19
+          switchInt(move _10) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 2 at $DIR/remove_storage_markers.rs:+2:14: +2:19
       }
   
       bb4: {
diff --git a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
index fe57e32a7ac..19b726e7484 100644
--- a/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.mir
@@ -68,9 +68,7 @@ fn array_casts() -> () {
         StorageLive(_3);                 // scope 1 at $DIR/retag.rs:+2:13: +2:19
         StorageLive(_4);                 // scope 1 at $DIR/retag.rs:+2:13: +2:19
         _4 = &mut _1;                    // scope 1 at $DIR/retag.rs:+2:13: +2:19
-        Retag(_4);                       // scope 1 at $DIR/retag.rs:+2:13: +2:19
         _3 = &raw mut (*_4);             // scope 1 at $DIR/retag.rs:+2:13: +2:19
-        Retag([raw] _3);                 // scope 1 at $DIR/retag.rs:+2:13: +2:19
         _2 = move _3 as *mut usize (Pointer(ArrayToPointer)); // scope 1 at $DIR/retag.rs:+2:13: +2:33
         StorageDead(_3);                 // scope 1 at $DIR/retag.rs:+2:32: +2:33
         StorageDead(_4);                 // scope 1 at $DIR/retag.rs:+2:33: +2:34
@@ -96,9 +94,7 @@ fn array_casts() -> () {
         StorageLive(_10);                // scope 4 at $DIR/retag.rs:+6:13: +6:15
         StorageLive(_11);                // scope 4 at $DIR/retag.rs:+6:13: +6:15
         _11 = &_8;                       // scope 4 at $DIR/retag.rs:+6:13: +6:15
-        Retag(_11);                      // scope 4 at $DIR/retag.rs:+6:13: +6:15
         _10 = &raw const (*_11);         // scope 4 at $DIR/retag.rs:+6:13: +6:15
-        Retag([raw] _10);                // scope 4 at $DIR/retag.rs:+6:13: +6:15
         _9 = move _10 as *const usize (Pointer(ArrayToPointer)); // scope 4 at $DIR/retag.rs:+6:13: +6:31
         StorageDead(_10);                // scope 4 at $DIR/retag.rs:+6:30: +6:31
         StorageDead(_11);                // scope 4 at $DIR/retag.rs:+6:31: +6:32
@@ -119,7 +115,6 @@ fn array_casts() -> () {
         StorageDead(_17);                // scope 6 at $DIR/retag.rs:+7:33: +7:34
         _15 = (*_16);                    // scope 6 at $DIR/retag.rs:+7:25: +7:34
         _14 = &_15;                      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        Retag(_14);                      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageLive(_18);                // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _35 = const _;                   // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
                                          // mir::Constant
@@ -127,7 +122,6 @@ fn array_casts() -> () {
                                          // + literal: Const { ty: &usize, val: Unevaluated(array_casts, [], Some(promoted[0])) }
         Retag(_35);                      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _18 = &(*_35);                   // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        Retag(_18);                      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         Deinit(_13);                     // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         (_13.0: &usize) = move _14;      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         (_13.1: &usize) = move _18;      // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
@@ -151,7 +145,7 @@ fn array_casts() -> () {
         StorageDead(_24);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _22 = Not(move _23);             // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageDead(_23);                // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        switchInt(move _22) -> [false: bb4, otherwise: bb3]; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+        switchInt(move _22) -> [0: bb4, otherwise: bb3]; // scope 7 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
     }
 
     bb3: {
@@ -164,15 +158,11 @@ fn array_casts() -> () {
         StorageLive(_30);                // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageLive(_31);                // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _31 = &(*_20);                   // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        Retag(_31);                      // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _30 = &(*_31);                   // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        Retag(_30);                      // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageLive(_32);                // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageLive(_33);                // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _33 = &(*_21);                   // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        Retag(_33);                      // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         _32 = &(*_33);                   // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-        Retag(_32);                      // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         StorageLive(_34);                // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         Deinit(_34);                     // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
         discriminant(_34) = 0;           // scope 8 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
diff --git a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
index cdc413c568f..14f297e948b 100644
--- a/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
+++ b/src/test/mir-opt/retag.core.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
@@ -6,7 +6,6 @@ fn std::ptr::drop_in_place(_1: *mut Test) -> () {
     let mut _3: ();                      // in scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
 
     bb0: {
-        Retag([raw] _1);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
         _2 = &mut (*_1);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
         _3 = <Test as Drop>::drop(move _2) -> bb1; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
                                          // mir::Constant
diff --git a/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir
index 96fc7e6493a..9e5c119a2b2 100644
--- a/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir
@@ -15,7 +15,6 @@ fn main::{closure#0}(_1: &[closure@main::{closure#0}], _2: &i32) -> &i32 {
         _3 = _2;                         // scope 0 at $DIR/retag.rs:+1:18: +1:19
         Retag(_3);                       // scope 0 at $DIR/retag.rs:+1:18: +1:19
         _0 = &(*_2);                     // scope 1 at $DIR/retag.rs:+2:9: +2:10
-        Retag(_0);                       // scope 1 at $DIR/retag.rs:+2:9: +2:10
         StorageDead(_3);                 // scope 0 at $DIR/retag.rs:+3:5: +3:6
         return;                          // scope 0 at $DIR/retag.rs:+3:6: +3:6
     }
diff --git a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
index 81225b44ebf..b853e450541 100644
--- a/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.mir
@@ -65,13 +65,10 @@ fn main() -> () {
         Deinit(_5);                      // scope 1 at $DIR/retag.rs:+3:17: +3:24
         (_5.0: i32) = const 0_i32;       // scope 1 at $DIR/retag.rs:+3:17: +3:24
         _4 = &_5;                        // scope 1 at $DIR/retag.rs:+3:17: +3:36
-        Retag(_4);                       // scope 1 at $DIR/retag.rs:+3:17: +3:36
         StorageLive(_6);                 // scope 1 at $DIR/retag.rs:+3:29: +3:35
         StorageLive(_7);                 // scope 1 at $DIR/retag.rs:+3:29: +3:35
         _7 = &mut _1;                    // scope 1 at $DIR/retag.rs:+3:29: +3:35
-        Retag(_7);                       // scope 1 at $DIR/retag.rs:+3:29: +3:35
         _6 = &mut (*_7);                 // scope 1 at $DIR/retag.rs:+3:29: +3:35
-        Retag([2phase] _6);              // scope 1 at $DIR/retag.rs:+3:29: +3:35
         _3 = Test::foo(move _4, move _6) -> [return: bb1, unwind: bb8]; // scope 1 at $DIR/retag.rs:+3:17: +3:36
                                          // mir::Constant
                                          // + span: $DIR/retag.rs:33:25: 33:28
@@ -93,7 +90,6 @@ fn main() -> () {
         _9 = move _3;                    // scope 2 at $DIR/retag.rs:+4:19: +4:20
         Retag(_9);                       // scope 2 at $DIR/retag.rs:+4:19: +4:20
         _8 = &mut (*_9);                 // scope 2 at $DIR/retag.rs:+4:19: +4:20
-        Retag(_8);                       // scope 2 at $DIR/retag.rs:+4:19: +4:20
         StorageDead(_9);                 // scope 2 at $DIR/retag.rs:+4:22: +4:23
         StorageLive(_10);                // scope 3 at $DIR/retag.rs:+5:13: +5:14
         _10 = move _8;                   // scope 3 at $DIR/retag.rs:+5:17: +5:18
@@ -101,7 +97,6 @@ fn main() -> () {
         StorageLive(_11);                // scope 4 at $DIR/retag.rs:+7:13: +7:15
         StorageLive(_12);                // scope 4 at $DIR/retag.rs:+7:18: +7:29
         _12 = &raw mut (*_10);           // scope 4 at $DIR/retag.rs:+7:18: +7:19
-        Retag([raw] _12);                // scope 4 at $DIR/retag.rs:+7:18: +7:19
         _11 = _12;                       // scope 4 at $DIR/retag.rs:+7:18: +7:29
         StorageDead(_12);                // scope 4 at $DIR/retag.rs:+7:29: +7:30
         _2 = const ();                   // scope 1 at $DIR/retag.rs:+2:5: +8:6
@@ -122,9 +117,7 @@ fn main() -> () {
         StorageLive(_17);                // scope 6 at $DIR/retag.rs:+15:16: +15:18
         StorageLive(_18);                // scope 6 at $DIR/retag.rs:+15:16: +15:18
         _18 = &_1;                       // scope 6 at $DIR/retag.rs:+15:16: +15:18
-        Retag(_18);                      // scope 6 at $DIR/retag.rs:+15:16: +15:18
         _17 = &(*_18);                   // scope 6 at $DIR/retag.rs:+15:16: +15:18
-        Retag(_17);                      // scope 6 at $DIR/retag.rs:+15:16: +15:18
         _15 = move _16(move _17) -> bb3; // scope 6 at $DIR/retag.rs:+15:14: +15:19
     }
 
@@ -139,7 +132,6 @@ fn main() -> () {
         Deinit(_21);                     // scope 7 at $DIR/retag.rs:+18:5: +18:12
         (_21.0: i32) = const 0_i32;      // scope 7 at $DIR/retag.rs:+18:5: +18:12
         _20 = &_21;                      // scope 7 at $DIR/retag.rs:+18:5: +18:24
-        Retag(_20);                      // scope 7 at $DIR/retag.rs:+18:5: +18:24
         StorageLive(_22);                // scope 7 at $DIR/retag.rs:+18:21: +18:23
         StorageLive(_23);                // scope 7 at $DIR/retag.rs:+18:21: +18:23
         _28 = const _;                   // scope 7 at $DIR/retag.rs:+18:21: +18:23
@@ -148,9 +140,7 @@ fn main() -> () {
                                          // + literal: Const { ty: &i32, val: Unevaluated(main, [], Some(promoted[0])) }
         Retag(_28);                      // scope 7 at $DIR/retag.rs:+18:21: +18:23
         _23 = &(*_28);                   // scope 7 at $DIR/retag.rs:+18:21: +18:23
-        Retag(_23);                      // scope 7 at $DIR/retag.rs:+18:21: +18:23
         _22 = &(*_23);                   // scope 7 at $DIR/retag.rs:+18:21: +18:23
-        Retag(_22);                      // scope 7 at $DIR/retag.rs:+18:21: +18:23
         _19 = Test::foo_shr(move _20, move _22) -> [return: bb4, unwind: bb7]; // scope 7 at $DIR/retag.rs:+18:5: +18:24
                                          // mir::Constant
                                          // + span: $DIR/retag.rs:48:13: 48:20
@@ -171,7 +161,6 @@ fn main() -> () {
         StorageLive(_25);                // scope 7 at $DIR/retag.rs:+21:9: +21:11
         StorageLive(_26);                // scope 7 at $DIR/retag.rs:+21:14: +21:28
         _26 = &raw const (*_15);         // scope 7 at $DIR/retag.rs:+21:14: +21:16
-        Retag([raw] _26);                // scope 7 at $DIR/retag.rs:+21:14: +21:16
         _25 = _26;                       // scope 7 at $DIR/retag.rs:+21:14: +21:28
         StorageDead(_26);                // scope 7 at $DIR/retag.rs:+21:28: +21:29
         StorageLive(_27);                // scope 8 at $DIR/retag.rs:+23:5: +23:18
diff --git a/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir
index 08fd655ae29..4b50205fa80 100644
--- a/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/retag.{impl#0}-foo.SimplifyCfg-elaborate-drops.after.mir
@@ -11,9 +11,7 @@ fn <impl at $DIR/retag.rs:12:1: 12:10>::foo(_1: &Test, _2: &mut i32) -> &mut i32
         Retag([fn entry] _2);            // scope 0 at $DIR/retag.rs:+0:23: +0:24
         StorageLive(_3);                 // scope 0 at $DIR/retag.rs:+1:9: +1:10
         _3 = &mut (*_2);                 // scope 0 at $DIR/retag.rs:+1:9: +1:10
-        Retag(_3);                       // scope 0 at $DIR/retag.rs:+1:9: +1:10
         _0 = &mut (*_3);                 // scope 0 at $DIR/retag.rs:+1:9: +1:10
-        Retag(_0);                       // scope 0 at $DIR/retag.rs:+1:9: +1:10
         StorageDead(_3);                 // scope 0 at $DIR/retag.rs:+2:5: +2:6
         return;                          // scope 0 at $DIR/retag.rs:+2:6: +2:6
     }
diff --git a/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
index b28c6f687f7..6ae16bdb5b8 100644
--- a/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
+++ b/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
@@ -53,14 +53,14 @@
           StorageLive(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9
           _4 = _1;                         // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9
           _10 = discriminant(_4);          // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
--         switchInt(move _10) -> [0_isize: bb7, 1_isize: bb5, otherwise: bb6]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-+         switchInt(move _10) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+-         switchInt(move _10) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++         switchInt(move _10) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
       }
   
       bb1: {
 -         StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
 -         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
--         switchInt(move _5) -> [0_isize: bb2, 1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+-         switchInt(move _5) -> [0: bb2, 1: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
 -     }
 - 
 -     bb2: {
@@ -118,7 +118,7 @@
 -         goto -> bb1;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
 +         StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
 +         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-+         switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
++         switchInt(move _5) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
       }
   
 -     bb6: {
@@ -140,7 +140,7 @@
 -         goto -> bb1;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
 +         StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
 +         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-+         switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
++         switchInt(move _5) -> [0: bb1, 1: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
       }
   
 -     bb8: {
diff --git a/src/test/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff b/src/test/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff
index 43797908136..8cc0c6a1835 100644
--- a/src/test/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff
+++ b/src/test/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff
@@ -30,7 +30,7 @@
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
           _3 = discriminant(_1);           // scope 0 at $DIR/separate_const_switch.rs:+6:15: +6:16
-          switchInt(move _3) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+6:9: +6:16
+          switchInt(move _3) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+6:9: +6:16
       }
   
       bb1: {
@@ -45,7 +45,7 @@
           StorageDead(_6);                 // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44
 -         goto -> bb4;                     // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44
 +         _8 = discriminant(_2);           // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
-+         switchInt(move _8) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
++         switchInt(move _8) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
       }
   
       bb2: {
@@ -67,8 +67,8 @@
 - 
 -     bb4: {
           _8 = discriminant(_2);           // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
--         switchInt(move _8) -> [0_isize: bb7, 1_isize: bb5, otherwise: bb6]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
-+         switchInt(move _8) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
+-         switchInt(move _8) -> [0: bb7, 1: bb5, otherwise: bb6]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
++         switchInt(move _8) -> [0: bb6, 1: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
       }
   
 -     bb5: {
diff --git a/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff
index e068b81bc3b..8eb1aa1f3b3 100644
--- a/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff
+++ b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-early-opt.diff
@@ -25,9 +25,9 @@
       }
   
 -     bb3: {
--         switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:+2:12: +2:17
+-         switchInt(move _2) -> [0: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:+2:12: +2:17
 +     bb2: {
-+         switchInt(move _2) -> [false: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:+2:12: +2:17
++         switchInt(move _2) -> [0: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify_cfg.rs:+2:12: +2:17
       }
   
 -     bb4: {
diff --git a/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff
index f693798eb94..1e66b1f703e 100644
--- a/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff
+++ b/src/test/mir-opt/simplify_cfg.main.SimplifyCfg-initial.diff
@@ -26,7 +26,7 @@
       }
   
       bb3: {
-          switchInt(move _2) -> [false: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:+2:12: +2:17
+          switchInt(move _2) -> [0: bb5, otherwise: bb4]; // scope 0 at $DIR/simplify_cfg.rs:+2:12: +2:17
       }
   
       bb4: {
diff --git a/src/test/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff b/src/test/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff
index 9b1bea2704b..aea01147443 100644
--- a/src/test/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff
+++ b/src/test/mir-opt/simplify_if.main.SimplifyConstCondition-after-const-prop.diff
@@ -9,7 +9,7 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/simplify_if.rs:+1:8: +1:13
           _1 = const false;                // scope 0 at $DIR/simplify_if.rs:+1:8: +1:13
--         switchInt(const false) -> [false: bb3, otherwise: bb1]; // scope 0 at $DIR/simplify_if.rs:+1:8: +1:13
+-         switchInt(const false) -> [0: bb3, otherwise: bb1]; // scope 0 at $DIR/simplify_if.rs:+1:8: +1:13
 +         goto -> bb3;                     // scope 0 at $DIR/simplify_if.rs:+1:8: +1:13
       }
   
diff --git a/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff
index 8feddcef2ce..a2b55229303 100644
--- a/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify_locals_fixedpoint.foo.SimplifyLocals.diff
@@ -29,12 +29,12 @@
           StorageDead(_3);                 // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:68: +1:69
           StorageDead(_2);                 // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:68: +1:69
           _5 = discriminant((_1.0: std::option::Option<u8>)); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27
-          switchInt(move _5) -> [1_isize: bb1, otherwise: bb3]; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27
+          switchInt(move _5) -> [1: bb1, otherwise: bb3]; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27
       }
   
       bb1: {
           _4 = discriminant((_1.1: std::option::Option<T>)); // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27
-          switchInt(move _4) -> [0_isize: bb2, otherwise: bb3]; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27
+          switchInt(move _4) -> [0: bb2, otherwise: bb3]; // scope 1 at $DIR/simplify_locals_fixedpoint.rs:+1:12: +1:27
       }
   
       bb2: {
diff --git a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff
index 6e7294003af..9ec138dd82f 100644
--- a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff
+++ b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.diff
@@ -18,7 +18,7 @@
 -         _5 = const false;                // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+1:11: +1:12
 -         _5 = const true;                 // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+1:11: +1:12
           _2 = discriminant(_1);           // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+1:11: +1:12
-          switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+1:5: +1:12
+          switchInt(move _2) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_locals_removes_unused_discriminant_reads.rs:+1:5: +1:12
       }
   
       bb1: {
diff --git a/src/test/mir-opt/simplify_match.main.ConstProp.diff b/src/test/mir-opt/simplify_match.main.ConstProp.diff
index e4f9a4c12d9..f00ac5716a7 100644
--- a/src/test/mir-opt/simplify_match.main.ConstProp.diff
+++ b/src/test/mir-opt/simplify_match.main.ConstProp.diff
@@ -16,8 +16,8 @@
 -         _1 = _2;                         // scope 1 at $DIR/simplify_match.rs:+1:28: +1:29
 +         _1 = const false;                // scope 1 at $DIR/simplify_match.rs:+1:28: +1:29
           StorageDead(_2);                 // scope 0 at $DIR/simplify_match.rs:+1:30: +1:31
--         switchInt(_1) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:+1:5: +1:31
-+         switchInt(const false) -> [false: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:+1:5: +1:31
+-         switchInt(_1) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:+1:5: +1:31
++         switchInt(const false) -> [0: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_match.rs:+1:5: +1:31
       }
   
       bb1: {
diff --git a/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir b/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir
index 31ccf14549c..391b00effac 100644
--- a/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir
+++ b/src/test/mir-opt/slice_drop_shim.core.ptr-drop_in_place.[String].AddMovesForPackedDrops.before.mir
@@ -37,7 +37,7 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
 
     bb4 (cleanup): {
         _6 = Eq(_4, _3);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        switchInt(move _6) -> [false: bb3, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        switchInt(move _6) -> [0: bb3, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     }
 
     bb5: {
@@ -48,7 +48,7 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
 
     bb6: {
         _8 = Eq(_4, _3);                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        switchInt(move _8) -> [false: bb5, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        switchInt(move _8) -> [0: bb5, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     }
 
     bb7: {
@@ -68,7 +68,7 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
 
     bb10 (cleanup): {
         _12 = Eq(_9, _10);               // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        switchInt(move _12) -> [false: bb9, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        switchInt(move _12) -> [0: bb9, otherwise: bb2]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     }
 
     bb11: {
@@ -79,7 +79,7 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
 
     bb12: {
         _14 = Eq(_9, _10);               // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        switchInt(move _14) -> [false: bb11, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        switchInt(move _14) -> [0: bb11, otherwise: bb1]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     }
 
     bb13: {
@@ -96,6 +96,6 @@ fn std::ptr::drop_in_place(_1: *mut [String]) -> () {
     bb15: {
         _2 = SizeOf(std::string::String); // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
         _3 = Len((*_1));                 // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
-        switchInt(move _2) -> [0_usize: bb8, otherwise: bb14]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
+        switchInt(move _2) -> [0: bb8, otherwise: bb14]; // scope 0 at $SRC_DIR/core/src/ptr/mod.rs:+0:1: +0:56
     }
 }
diff --git a/src/test/mir-opt/sroa.enums.ScalarReplacementOfAggregates.diff b/src/test/mir-opt/sroa.enums.ScalarReplacementOfAggregates.diff
index 7c7e87c32a2..a5488c1ec7b 100644
--- a/src/test/mir-opt/sroa.enums.ScalarReplacementOfAggregates.diff
+++ b/src/test/mir-opt/sroa.enums.ScalarReplacementOfAggregates.diff
@@ -21,7 +21,7 @@
           discriminant(_2) = 1;            // scope 1 at $DIR/sroa.rs:+1:22: +1:29
           StorageDead(_3);                 // scope 1 at $DIR/sroa.rs:+1:28: +1:29
           _4 = discriminant(_2);           // scope 1 at $DIR/sroa.rs:+1:12: +1:19
-          switchInt(move _4) -> [1_isize: bb1, otherwise: bb2]; // scope 1 at $DIR/sroa.rs:+1:12: +1:19
+          switchInt(move _4) -> [1: bb1, otherwise: bb2]; // scope 1 at $DIR/sroa.rs:+1:12: +1:19
       }
   
       bb1: {
diff --git a/src/test/mir-opt/try_identity_e2e.new.PreCodegen.after.mir b/src/test/mir-opt/try_identity_e2e.new.PreCodegen.after.mir
index 30185f3ffab..b254bfeb7c9 100644
--- a/src/test/mir-opt/try_identity_e2e.new.PreCodegen.after.mir
+++ b/src/test/mir-opt/try_identity_e2e.new.PreCodegen.after.mir
@@ -26,7 +26,7 @@ fn new(_1: Result<T, E>) -> Result<T, E> {
     bb0: {
         StorageLive(_2);                 // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
         _3 = discriminant(_1);           // scope 0 at $DIR/try_identity_e2e.rs:+3:19: +3:20
-        switchInt(move _3) -> [0_isize: bb2, 1_isize: bb1, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+3:13: +3:20
+        switchInt(move _3) -> [0: bb2, 1: bb1, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+3:13: +3:20
     }
 
     bb1: {
@@ -35,7 +35,7 @@ fn new(_1: Result<T, E>) -> Result<T, E> {
         ((_2 as Break).0: E) = move _5;  // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
         discriminant(_2) = 1;            // scope 2 at $DIR/try_identity_e2e.rs:+5:27: +5:48
         _6 = discriminant(_2);           // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
-        switchInt(move _6) -> [0_isize: bb5, 1_isize: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
+        switchInt(move _6) -> [0: bb5, 1: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
     }
 
     bb2: {
@@ -44,7 +44,7 @@ fn new(_1: Result<T, E>) -> Result<T, E> {
         ((_2 as Continue).0: T) = move _4; // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
         discriminant(_2) = 0;            // scope 1 at $DIR/try_identity_e2e.rs:+4:26: +4:50
         _6 = discriminant(_2);           // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +7:10
-        switchInt(move _6) -> [0_isize: bb5, 1_isize: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
+        switchInt(move _6) -> [0: bb5, 1: bb3, otherwise: bb4]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +7:10
     }
 
     bb3: {
diff --git a/src/test/mir-opt/try_identity_e2e.old.PreCodegen.after.mir b/src/test/mir-opt/try_identity_e2e.old.PreCodegen.after.mir
index 2a9c7408c66..cdbc0681cb8 100644
--- a/src/test/mir-opt/try_identity_e2e.old.PreCodegen.after.mir
+++ b/src/test/mir-opt/try_identity_e2e.old.PreCodegen.after.mir
@@ -15,7 +15,7 @@ fn old(_1: Result<T, E>) -> Result<T, E> {
 
     bb0: {
         _2 = discriminant(_1);           // scope 0 at $DIR/try_identity_e2e.rs:+2:15: +2:16
-        switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +2:16
+        switchInt(move _2) -> [0: bb3, 1: bb1, otherwise: bb2]; // scope 0 at $DIR/try_identity_e2e.rs:+2:9: +2:16
     }
 
     bb1: {
diff --git a/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir b/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
index 4aa5ba007f1..39ec0527759 100644
--- a/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
+++ b/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
@@ -18,7 +18,7 @@ fn main() -> () {
         Deinit(_2);                      // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
         discriminant(_2) = 2;            // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
         _3 = discriminant(_2);           // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
-        switchInt(move _3) -> [2_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
+        switchInt(move _3) -> [2: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
     }
 
     bb1: {
@@ -36,7 +36,7 @@ fn main() -> () {
         Deinit(_7);                      // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
         discriminant(_7) = 0;            // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
         _8 = discriminant(_7);           // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
-        switchInt(move _8) -> [4_isize: bb5, 5_isize: bb3, otherwise: bb4]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
+        switchInt(move _8) -> [4: bb5, 5: bb3, otherwise: bb4]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
     }
 
     bb2: {
diff --git a/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff b/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff
index c3d356aedb2..598413a1d82 100644
--- a/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff
+++ b/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff
@@ -19,8 +19,8 @@
           Deinit(_2);                      // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
           discriminant(_2) = 2;            // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
           _3 = discriminant(_2);           // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
--         switchInt(move _3) -> [0_isize: bb3, 1_isize: bb4, 2_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
-+         switchInt(move _3) -> [2_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
+-         switchInt(move _3) -> [0: bb3, 1: bb4, 2: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
++         switchInt(move _3) -> [2: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
       }
   
       bb1: {
@@ -65,7 +65,7 @@
           Deinit(_7);                      // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
           discriminant(_7) = 0;            // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
           _8 = discriminant(_7);           // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
-          switchInt(move _8) -> [4_isize: bb8, 5_isize: bb6, otherwise: bb7]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
+          switchInt(move _8) -> [4: bb8, 5: bb6, otherwise: bb7]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
       }
   
       bb6: {
diff --git a/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir b/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
index ec5612ad767..c8cd6f6c1ea 100644
--- a/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
+++ b/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
@@ -32,7 +32,7 @@ fn main() -> () {
         StorageLive(_4);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
         _4 = &(_1.1: Test1);             // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
         _5 = discriminant((*_4));        // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
-        switchInt(move _5) -> [2_isize: bb3, 3_isize: bb1, otherwise: bb2]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
+        switchInt(move _5) -> [2: bb3, 3: bb1, otherwise: bb2]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
     }
 
     bb1: {
@@ -66,7 +66,7 @@ fn main() -> () {
         StorageDead(_3);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+8:6: +8:7
         StorageLive(_9);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +15:6
         _10 = discriminant((_1.1: Test1)); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:11: +10:21
-        switchInt(move _10) -> [2_isize: bb7, 3_isize: bb5, otherwise: bb6]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
+        switchInt(move _10) -> [2: bb7, 3: bb5, otherwise: bb6]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
     }
 
     bb5: {
diff --git a/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff b/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff
index 77b358a4801..2aee6d2681d 100644
--- a/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff
+++ b/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff
@@ -33,8 +33,8 @@
           StorageLive(_4);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
           _4 = &(_1.1: Test1);             // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
           _5 = discriminant((*_4));        // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
--         switchInt(move _5) -> [0_isize: bb3, 1_isize: bb4, 2_isize: bb5, 3_isize: bb1, otherwise: bb2]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
-+         switchInt(move _5) -> [2_isize: bb5, 3_isize: bb1, otherwise: bb2]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
+-         switchInt(move _5) -> [0: bb3, 1: bb4, 2: bb5, 3: bb1, otherwise: bb2]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
++         switchInt(move _5) -> [2: bb5, 3: bb1, otherwise: bb2]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
       }
   
       bb1: {
@@ -87,8 +87,8 @@
           StorageDead(_3);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+8:6: +8:7
           StorageLive(_9);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +15:6
           _10 = discriminant((_1.1: Test1)); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:11: +10:21
--         switchInt(move _10) -> [0_isize: bb9, 1_isize: bb10, 2_isize: bb11, 3_isize: bb7, otherwise: bb8]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
-+         switchInt(move _10) -> [2_isize: bb11, 3_isize: bb7, otherwise: bb8]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
+-         switchInt(move _10) -> [0: bb9, 1: bb10, 2: bb11, 3: bb7, otherwise: bb8]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
++         switchInt(move _10) -> [2: bb11, 3: bb7, otherwise: bb8]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
       }
   
       bb7: {
diff --git a/src/test/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff b/src/test/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff
index 11d93fca7e0..58e085dd041 100644
--- a/src/test/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff
+++ b/src/test/mir-opt/uninhabited_fallthrough_elimination.eliminate_fallthrough.UninhabitedEnumBranching.diff
@@ -8,8 +8,8 @@
   
       bb0: {
           _2 = discriminant(_1);           // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:11: +1:12
--         switchInt(move _2) -> [1_isize: bb3, 2_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
-+         switchInt(move _2) -> [1_isize: bb3, 2_isize: bb2, otherwise: bb5]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
+-         switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
++         switchInt(move _2) -> [1: bb3, 2: bb2, otherwise: bb5]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
       }
   
       bb1: {
diff --git a/src/test/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff b/src/test/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff
index a7f8321ae34..e765851eb78 100644
--- a/src/test/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff
+++ b/src/test/mir-opt/uninhabited_fallthrough_elimination.keep_fallthrough.UninhabitedEnumBranching.diff
@@ -8,8 +8,8 @@
   
       bb0: {
           _2 = discriminant(_1);           // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:11: +1:12
--         switchInt(move _2) -> [0_isize: bb2, 1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
-+         switchInt(move _2) -> [1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
+-         switchInt(move _2) -> [0: bb2, 1: bb3, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
++         switchInt(move _2) -> [1: bb3, otherwise: bb1]; // scope 0 at $DIR/uninhabited_fallthrough_elimination.rs:+1:5: +1:12
       }
   
       bb1: {
diff --git a/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff b/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff
index 9cd4b8ccf33..848bff1d492 100644
--- a/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff
+++ b/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff
@@ -27,8 +27,8 @@
   
       bb1: {
           _2 = discriminant(_1);           // scope 1 at $DIR/unreachable.rs:+1:12: +1:20
--         switchInt(move _2) -> [1_isize: bb2, otherwise: bb6]; // scope 1 at $DIR/unreachable.rs:+1:12: +1:20
-+         switchInt(move _2) -> [1_isize: bb2, otherwise: bb3]; // scope 1 at $DIR/unreachable.rs:+1:12: +1:20
+-         switchInt(move _2) -> [1: bb2, otherwise: bb6]; // scope 1 at $DIR/unreachable.rs:+1:12: +1:20
++         switchInt(move _2) -> [1: bb2, otherwise: bb3]; // scope 1 at $DIR/unreachable.rs:+1:12: +1:20
       }
   
       bb2: {
@@ -38,7 +38,7 @@
 -         StorageLive(_5);                 // scope 2 at $DIR/unreachable.rs:+4:9: +8:10
 -         StorageLive(_6);                 // scope 2 at $DIR/unreachable.rs:+4:12: +4:16
 -         _6 = const true;                 // scope 2 at $DIR/unreachable.rs:+4:12: +4:16
--         switchInt(move _6) -> [false: bb4, otherwise: bb3]; // scope 2 at $DIR/unreachable.rs:+4:12: +4:16
+-         switchInt(move _6) -> [0: bb4, otherwise: bb3]; // scope 2 at $DIR/unreachable.rs:+4:12: +4:16
 +         unreachable;                     // scope 2 at $DIR/unreachable.rs:+4:12: +4:16
       }
   
diff --git a/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff b/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff
index afd6b00aac3..fb778470e53 100644
--- a/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff
+++ b/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff
@@ -29,7 +29,7 @@
   
       bb1: {
           _3 = discriminant(_2);           // scope 2 at $DIR/unreachable_diverging.rs:+2:12: +2:22
-          switchInt(move _3) -> [1_isize: bb2, otherwise: bb6]; // scope 2 at $DIR/unreachable_diverging.rs:+2:12: +2:22
+          switchInt(move _3) -> [1: bb2, otherwise: bb6]; // scope 2 at $DIR/unreachable_diverging.rs:+2:12: +2:22
       }
   
       bb2: {
@@ -38,7 +38,7 @@
           StorageLive(_5);                 // scope 2 at $DIR/unreachable_diverging.rs:+3:9: +5:10
           StorageLive(_6);                 // scope 2 at $DIR/unreachable_diverging.rs:+3:12: +3:13
           _6 = _1;                         // scope 2 at $DIR/unreachable_diverging.rs:+3:12: +3:13
-          switchInt(move _6) -> [false: bb4, otherwise: bb3]; // scope 2 at $DIR/unreachable_diverging.rs:+3:12: +3:13
+          switchInt(move _6) -> [0: bb4, otherwise: bb3]; // scope 2 at $DIR/unreachable_diverging.rs:+3:12: +3:13
       }
   
       bb3: {
diff --git a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff
index eef7011149d..984ef476e10 100644
--- a/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff
+++ b/src/test/mir-opt/while_let_loops.change_loop_body.ConstProp.diff
@@ -24,13 +24,13 @@
           Deinit(_3);                      // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
           discriminant(_3) = 0;            // scope 2 at $DIR/while_let_loops.rs:+2:28: +2:32
 -         _4 = discriminant(_3);           // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
--         switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
+-         switchInt(move _4) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
 +         _4 = const 0_isize;              // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
-+         switchInt(const 0_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
++         switchInt(const 0_isize) -> [1: bb1, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
       }
   
       bb1: {
-          switchInt(((_3 as Some).0: u32)) -> [0_u32: bb2, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
+          switchInt(((_3 as Some).0: u32)) -> [0: bb2, otherwise: bb3]; // scope 2 at $DIR/while_let_loops.rs:+2:15: +2:25
       }
   
       bb2: {
diff --git a/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir b/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir
index 68aa3e5db32..1556c240dc5 100644
--- a/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir
+++ b/src/test/mir-opt/while_storage.while_loop.PreCodegen.after.mir
@@ -24,7 +24,7 @@ fn while_loop(_1: bool) -> () {
 
     bb2: {
         StorageDead(_3);                 // scope 0 at $DIR/while_storage.rs:+1:21: +1:22
-        switchInt(move _2) -> [false: bb7, otherwise: bb3]; // scope 0 at $DIR/while_storage.rs:+1:11: +1:22
+        switchInt(move _2) -> [0: bb7, otherwise: bb3]; // scope 0 at $DIR/while_storage.rs:+1:11: +1:22
     }
 
     bb3: {
@@ -39,7 +39,7 @@ fn while_loop(_1: bool) -> () {
 
     bb4: {
         StorageDead(_5);                 // scope 0 at $DIR/while_storage.rs:+2:22: +2:23
-        switchInt(move _4) -> [false: bb6, otherwise: bb5]; // scope 0 at $DIR/while_storage.rs:+2:12: +2:23
+        switchInt(move _4) -> [0: bb6, otherwise: bb5]; // scope 0 at $DIR/while_storage.rs:+2:12: +2:23
     }
 
     bb5: {
diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
index 2c4309fbe66..3aa57d58908 100644
--- a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
+++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs
@@ -67,7 +67,7 @@ impl CodegenBackend for TheBackend {
             if crate_type != CrateType::Rlib {
                 sess.fatal(&format!("Crate type is {:?}", crate_type));
             }
-            let output_name = out_filename(sess, crate_type, &outputs, &*crate_name.as_str());
+            let output_name = out_filename(sess, crate_type, &outputs, crate_name);
             let mut out_file = ::std::fs::File::create(output_name).unwrap();
             write!(out_file, "This has been \"compiled\" successfully.").unwrap();
         }
diff --git a/src/test/run-make/coverage-reports/Makefile b/src/test/run-make/coverage-reports/Makefile
index 436aebf1174..d06cd9c6a54 100644
--- a/src/test/run-make/coverage-reports/Makefile
+++ b/src/test/run-make/coverage-reports/Makefile
@@ -80,7 +80,7 @@ ifdef RUSTC_BLESS_TEST
 	rm -f expected_*
 endif
 
-include clear_expected_if_blessed
+-include clear_expected_if_blessed
 
 %: $(SOURCEDIR)/lib/%.rs
 	# Compile the test library with coverage instrumentation
diff --git a/src/test/run-make/issue-71519/Makefile b/src/test/run-make/issue-71519/Makefile
index 16d9a56e6bf..57497f52053 100644
--- a/src/test/run-make/issue-71519/Makefile
+++ b/src/test/run-make/issue-71519/Makefile
@@ -2,6 +2,7 @@ include ../../run-make-fulldeps/tools.mk
 
 # ignore-msvc
 # needs-rust-lld
+# ignore-s390x lld does not yet support s390x as target
 all:
 	RUSTC_LOG=rustc_codegen_ssa::back::link=info $(RUSTC) -Z gcc-ld=lld -C link-args=-Wl,-v main.rs 2> $(TMPDIR)/output.txt
 	$(CGREP) -e "^LLD [0-9]+\.[0-9]+\.[0-9]+" < $(TMPDIR)/output.txt
diff --git a/src/test/rustdoc-gui/basic.goml b/src/test/rustdoc-gui/basic.goml
deleted file mode 100644
index 60292835bc0..00000000000
--- a/src/test/rustdoc-gui/basic.goml
+++ /dev/null
@@ -1,4 +0,0 @@
-goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
-assert: ("#functions")
-goto: "./struct.Foo.html"
-assert: ("div.item-decl")
diff --git a/src/test/rustdoc-gui/docblock-table.goml b/src/test/rustdoc-gui/docblock-table.goml
index 4e316ce0bcb..8645c1b1949 100644
--- a/src/test/rustdoc-gui/docblock-table.goml
+++ b/src/test/rustdoc-gui/docblock-table.goml
@@ -2,3 +2,50 @@ goto: "file://" + |DOC_PATH| + "/test_docs/doc_block_table/struct.DocBlockTable.
 
 compare-elements-css: (".impl-items .docblock table th", ".top-doc .docblock table th", ["border"])
 compare-elements-css: (".impl-items .docblock table td", ".top-doc .docblock table td", ["border"])
+
+define-function: (
+    "check-colors",
+    (theme, border_color, zebra_stripe_color),
+    [
+        ("local-storage", {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}),
+        ("reload"),
+        ("assert-css", (".top-doc .docblock table tbody tr:nth-child(1)", {
+            "background-color": "rgba(0, 0, 0, 0)",
+        })),
+        ("assert-css", (".top-doc .docblock table tbody tr:nth-child(2)", {
+            "background-color": |zebra_stripe_color|,
+        })),
+        ("assert-css", (".top-doc .docblock table tbody tr:nth-child(3)", {
+            "background-color": "rgba(0, 0, 0, 0)",
+        })),
+        ("assert-css", (".top-doc .docblock table tbody tr:nth-child(4)", {
+            "background-color": |zebra_stripe_color|,
+        })),
+        ("assert-css", (".top-doc .docblock table td", {
+            "border-style": "solid",
+            "border-width": "1px",
+            "border-color": |border_color|,
+        })),
+        ("assert-css", (".top-doc .docblock table th", {
+            "border-style": "solid",
+            "border-width": "1px",
+            "border-color": |border_color|,
+        })),
+    ]
+)
+
+call-function: ("check-colors", {
+    "theme": "dark",
+    "border_color": "rgb(224, 224, 224)",
+    "zebra_stripe_color": "rgb(42, 42, 42)",
+})
+call-function: ("check-colors", {
+    "theme": "ayu",
+    "border_color": "rgb(92, 103, 115)",
+    "zebra_stripe_color": "rgb(25, 31, 38)",
+})
+call-function: ("check-colors", {
+    "theme": "light",
+    "border_color": "rgb(224, 224, 224)",
+    "zebra_stripe_color": "rgb(245, 245, 245)",
+})
diff --git a/src/test/rustdoc-gui/scrape-examples-button-focus.goml b/src/test/rustdoc-gui/scrape-examples-button-focus.goml
index a222139f1dc..bba518db099 100644
--- a/src/test/rustdoc-gui/scrape-examples-button-focus.goml
+++ b/src/test/rustdoc-gui/scrape-examples-button-focus.goml
@@ -1,5 +1,6 @@
 goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test.html"
 
+// The next/prev buttons vertically scroll the code viewport between examples
 store-property: (initialScrollTop, ".scraped-example-list > .scraped-example pre", "scrollTop")
 focus: ".scraped-example-list > .scraped-example .next"
 press-key: "Enter"
@@ -12,6 +13,7 @@ assert-property: (".scraped-example-list > .scraped-example pre", {
 	"scrollTop": |initialScrollTop|
 })
 
+// The expand button increases the scrollHeight of the minimized code viewport
 store-property: (smallOffsetHeight, ".scraped-example-list > .scraped-example pre", "offsetHeight")
 assert-property-false: (".scraped-example-list > .scraped-example pre", {
 	"scrollHeight": |smallOffsetHeight|
diff --git a/src/test/rustdoc-gui/scrape-examples-toggle.goml b/src/test/rustdoc-gui/scrape-examples-toggle.goml
new file mode 100644
index 00000000000..ee720afb788
--- /dev/null
+++ b/src/test/rustdoc-gui/scrape-examples-toggle.goml
@@ -0,0 +1,14 @@
+goto: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
+
+// Clicking "More examples..." will open additional examples
+assert-attribute-false: (".more-examples-toggle", {"open": ""})
+click: ".more-examples-toggle"
+assert-attribute: (".more-examples-toggle", {"open": ""})
+
+// Toggling all docs will close additional examples
+click: "#toggle-all-docs"
+assert-attribute-false: (".more-examples-toggle", {"open": ""})
+
+// After re-opening the docs, the additional examples should stay closed
+click: "#toggle-all-docs"
+assert-attribute-false: (".more-examples-toggle", {"open": ""})
diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs
index 1340511d472..d6eeab803df 100644
--- a/src/test/rustdoc-gui/src/test_docs/lib.rs
+++ b/src/test/rustdoc-gui/src/test_docs/lib.rs
@@ -343,6 +343,9 @@ pub mod doc_block_table {
     /// | header1                  | header2                  |
     /// |--------------------------|--------------------------|
     /// | Lorem Ipsum, Lorem Ipsum | Lorem Ipsum, Lorem Ipsum |
+    /// | Lorem Ipsum, Lorem Ipsum | Lorem Ipsum, Lorem Ipsum |
+    /// | Lorem Ipsum, Lorem Ipsum | Lorem Ipsum, Lorem Ipsum |
+    /// | Lorem Ipsum, Lorem Ipsum | Lorem Ipsum, Lorem Ipsum |
     pub struct DocBlockTable {}
 
     impl DocBlockTableTrait for DocBlockTable {
diff --git a/src/test/rustdoc-gui/stab-badge.goml b/src/test/rustdoc-gui/stab-badge.goml
new file mode 100644
index 00000000000..aaed8440a40
--- /dev/null
+++ b/src/test/rustdoc-gui/stab-badge.goml
@@ -0,0 +1,41 @@
+// All stability badges should have rounded corners and colored backgrounds.
+goto: "file://" + |DOC_PATH| + "/test_docs/index.html"
+show-text: true
+define-function: (
+	"check-badge",
+	(theme, background, color),
+	[
+        ("local-storage", {"rustdoc-use-system-theme": "false", "rustdoc-theme": |theme|}),
+        ("goto", "file://" + |DOC_PATH| + "/test_docs/index.html"),
+		("assert", (".docblock .stab")),
+		("assert", (".item-table .stab")),
+		("assert-css", (".stab", {
+			"border-radius": "3px",
+			"color": |color|,
+			"background-color": |background|,
+		})),
+        ("goto", "file://" + |DOC_PATH| + "/test_docs/fn.replaced_function.html"),
+		("assert", (".item-info .stab")),
+		("assert-css", (".stab", {
+			"border-radius": "3px",
+			"color": |color|,
+			"background-color": |background|,
+		})),
+	]
+)
+
+call-function: ("check-badge", {
+	"theme": "ayu",
+	"color": "rgb(197, 197, 197)",
+	"background": "rgb(49, 69, 89)",
+})
+call-function: ("check-badge", {
+	"theme": "dark",
+	"color": "rgb(221, 221, 221)",
+	"background": "rgb(49, 69, 89)",
+})
+call-function: ("check-badge", {
+	"theme": "light",
+	"color": "rgb(0, 0, 0)",
+	"background": "rgb(255, 245, 214)",
+})
diff --git a/src/test/rustdoc/const-evalutation-ice.rs b/src/test/rustdoc-ui/const-evalutation-ice.rs
index 68c7f9c5686..0dd3bcaa289 100644
--- a/src/test/rustdoc/const-evalutation-ice.rs
+++ b/src/test/rustdoc-ui/const-evalutation-ice.rs
@@ -7,4 +7,5 @@ pub struct S {
     s: Cell<usize>
 }
 
-pub const N: usize = 0 - (mem::size_of::<S>() != 4) as usize;
+pub const N: usize = 0 - (mem::size_of::<S>() != 400) as usize;
+//~^ ERROR evaluation of constant value failed
diff --git a/src/test/rustdoc-ui/const-evalutation-ice.stderr b/src/test/rustdoc-ui/const-evalutation-ice.stderr
new file mode 100644
index 00000000000..5d9c16c0765
--- /dev/null
+++ b/src/test/rustdoc-ui/const-evalutation-ice.stderr
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/const-evalutation-ice.rs:10:22
+   |
+LL | pub const N: usize = 0 - (mem::size_of::<S>() != 400) as usize;
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `0_usize - 1_usize`, which would overflow
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/rustdoc-ui/doc-cfg.stderr b/src/test/rustdoc-ui/doc-cfg.stderr
index b379f6febe2..14b7b17e04d 100644
--- a/src/test/rustdoc-ui/doc-cfg.stderr
+++ b/src/test/rustdoc-ui/doc-cfg.stderr
@@ -2,7 +2,7 @@ error: `cfg` predicate is not specified
   --> $DIR/doc-cfg.rs:3:7
    |
 LL | #[doc(cfg(), cfg(foo, bar))]
-   |       ^^^^^
+   |       ^^^^^ help: expected syntax is: `cfg(/* predicate */)`
 
 error: multiple `cfg` predicates are specified
   --> $DIR/doc-cfg.rs:3:23
@@ -14,7 +14,7 @@ error: `cfg` predicate is not specified
   --> $DIR/doc-cfg.rs:7:7
    |
 LL | #[doc(cfg())]
-   |       ^^^^^
+   |       ^^^^^ help: expected syntax is: `cfg(/* predicate */)`
 
 error: multiple `cfg` predicates are specified
   --> $DIR/doc-cfg.rs:8:16
diff --git a/src/test/ui/async-await/in-trait/nested-rpit.rs b/src/test/ui/async-await/in-trait/nested-rpit.rs
new file mode 100644
index 00000000000..ae8e0aed0cc
--- /dev/null
+++ b/src/test/ui/async-await/in-trait/nested-rpit.rs
@@ -0,0 +1,17 @@
+// check-pass
+// edition: 2021
+
+#![feature(async_fn_in_trait)]
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::future::Future;
+use std::marker::PhantomData;
+
+trait Lockable<K, V> {
+    async fn lock_all_entries(&self) -> impl Future<Output = Guard<'_>>;
+}
+
+struct Guard<'a>(PhantomData<&'a ()>);
+
+fn main() {}
diff --git a/src/test/ui/borrowck/issue-81899.stderr b/src/test/ui/borrowck/issue-81899.stderr
index a4d5f212188..1b03bc3af9c 100644
--- a/src/test/ui/borrowck/issue-81899.stderr
+++ b/src/test/ui/borrowck/issue-81899.stderr
@@ -1,15 +1,19 @@
 error[E0080]: evaluation of constant value failed
   --> $DIR/issue-81899.rs:11:5
    |
-LL | const _CONST: &[u8] = &f(&[], |_| {});
-   |                        -------------- inside `_CONST` at $DIR/issue-81899.rs:4:24
-...
+LL |     panic!()
+   |     ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/issue-81899.rs:11:5
+   |
+note: inside `f::<[closure@$DIR/issue-81899.rs:4:31: 4:34]>`
+  --> $DIR/issue-81899.rs:11:5
+   |
 LL |     panic!()
    |     ^^^^^^^^
-   |     |
-   |     the evaluated program panicked at 'explicit panic', $DIR/issue-81899.rs:11:5
-   |     inside `f::<[closure@$DIR/issue-81899.rs:4:31: 4:34]>` at $SRC_DIR/std/src/panic.rs:LL:COL
+note: inside `_CONST`
+  --> $DIR/issue-81899.rs:4:24
    |
+LL | const _CONST: &[u8] = &f(&[], |_| {});
+   |                        ^^^^^^^^^^^^^^
    = 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)
 
 note: erroneous constant used
diff --git a/src/test/ui/borrowck/issue-88434-minimal-example.stderr b/src/test/ui/borrowck/issue-88434-minimal-example.stderr
index b95ddc49c99..a5a571c6d4d 100644
--- a/src/test/ui/borrowck/issue-88434-minimal-example.stderr
+++ b/src/test/ui/borrowck/issue-88434-minimal-example.stderr
@@ -1,15 +1,19 @@
 error[E0080]: evaluation of constant value failed
   --> $DIR/issue-88434-minimal-example.rs:10:5
    |
-LL | const _CONST: &() = &f(&|_| {});
-   |                      ---------- inside `_CONST` at $DIR/issue-88434-minimal-example.rs:3:22
-...
+LL |     panic!()
+   |     ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:10:5
+   |
+note: inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:3:25: 3:28]>`
+  --> $DIR/issue-88434-minimal-example.rs:10:5
+   |
 LL |     panic!()
    |     ^^^^^^^^
-   |     |
-   |     the evaluated program panicked at 'explicit panic', $DIR/issue-88434-minimal-example.rs:10:5
-   |     inside `f::<[closure@$DIR/issue-88434-minimal-example.rs:3:25: 3:28]>` at $SRC_DIR/std/src/panic.rs:LL:COL
+note: inside `_CONST`
+  --> $DIR/issue-88434-minimal-example.rs:3:22
    |
+LL | const _CONST: &() = &f(&|_| {});
+   |                      ^^^^^^^^^^
    = 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)
 
 note: erroneous constant used
diff --git a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr
index 604a6577639..00023c459a8 100644
--- a/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr
+++ b/src/test/ui/borrowck/issue-88434-removal-index-should-be-less.stderr
@@ -1,15 +1,19 @@
 error[E0080]: evaluation of constant value failed
   --> $DIR/issue-88434-removal-index-should-be-less.rs:10:5
    |
-LL | const _CONST: &[u8] = &f(&[], |_| {});
-   |                        -------------- inside `_CONST` at $DIR/issue-88434-removal-index-should-be-less.rs:3:24
-...
+LL |     panic!()
+   |     ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:10:5
+   |
+note: inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:34]>`
+  --> $DIR/issue-88434-removal-index-should-be-less.rs:10:5
+   |
 LL |     panic!()
    |     ^^^^^^^^
-   |     |
-   |     the evaluated program panicked at 'explicit panic', $DIR/issue-88434-removal-index-should-be-less.rs:10:5
-   |     inside `f::<[closure@$DIR/issue-88434-removal-index-should-be-less.rs:3:31: 3:34]>` at $SRC_DIR/std/src/panic.rs:LL:COL
+note: inside `_CONST`
+  --> $DIR/issue-88434-removal-index-should-be-less.rs:3:24
    |
+LL | const _CONST: &[u8] = &f(&[], |_| {});
+   |                        ^^^^^^^^^^^^^^
    = 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)
 
 note: erroneous constant used
diff --git a/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
index d4bd673b84e..d5b4349c00f 100644
--- a/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
+++ b/src/test/ui/conditional-compilation/cfg-attr-syntax-validation.stderr
@@ -14,7 +14,7 @@ error: `cfg` predicate is not specified
   --> $DIR/cfg-attr-syntax-validation.rs:7:1
    |
 LL | #[cfg()]
-   | ^^^^^^^^
+   | ^^^^^^^^ help: expected syntax is: `cfg(/* predicate */)`
 
 error: multiple `cfg` predicates are specified
   --> $DIR/cfg-attr-syntax-validation.rs:10:10
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-105257.rs b/src/test/ui/const-generics/generic_const_exprs/issue-105257.rs
new file mode 100644
index 00000000000..d8b23bc01a9
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-105257.rs
@@ -0,0 +1,9 @@
+#![feature(generic_const_exprs)]
+#![allow(incomplete_features)]
+
+trait Trait<T> {
+    fn fnc<const N: usize = "">(&self) {} //~ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+    fn foo<const N: usize = { std::mem::size_of::<T>() }>(&self) {} //~ERROR defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-105257.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-105257.stderr
new file mode 100644
index 00000000000..ed7a8cb19a4
--- /dev/null
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-105257.stderr
@@ -0,0 +1,14 @@
+error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+  --> $DIR/issue-105257.rs:5:12
+   |
+LL |     fn fnc<const N: usize = "">(&self) {}
+   |            ^^^^^^^^^^^^^^^^^^^
+
+error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+  --> $DIR/issue-105257.rs:6:12
+   |
+LL |     fn foo<const N: usize = { std::mem::size_of::<T>() }>(&self) {}
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr
index c90774e944f..029528c3a81 100644
--- a/src/test/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-79518-default_trait_method_normalization.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/issue-79518-default_trait_method_normalization.rs:16:32
    |
 LL |         Self::AssocInstance == [(); std::mem::size_of::<Self::Assoc>()];
-   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found array `[(); _]`
+   |         -------------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found array `[(); _]`
+   |         |
+   |         expected because this is `<Self as Foo>::Assoc`
    |
    = note: expected associated type `<Self as Foo>::Assoc`
                         found array `[(); _]`
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr
index 1b502642eb7..bf1b411ee7c 100644
--- a/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-80742.stderr
@@ -2,15 +2,18 @@ error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
    |
 LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |     |
-   |     size_of called on unsized type `dyn Debug`
-   |     inside `std::mem::size_of::<dyn Debug>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ size_of called on unsized type `dyn Debug`
+   |
+note: inside `std::mem::size_of::<dyn Debug>`
+  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
    |
-  ::: $DIR/issue-80742.rs:22:10
+LL |     intrinsics::size_of::<T>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `Inline::<dyn Debug>::{constant#0}`
+  --> $DIR/issue-80742.rs:22:10
    |
 LL |     [u8; size_of::<T>() + 1]: ,
-   |          -------------- inside `Inline::<dyn Debug>::{constant#0}` at $DIR/issue-80742.rs:22:10
+   |          ^^^^^^^^^^^^^^
 
 error[E0599]: the function or associated item `new` exists for struct `Inline<dyn Debug>`, but its trait bounds were not satisfied
   --> $DIR/issue-80742.rs:30:36
@@ -33,15 +36,18 @@ error[E0080]: evaluation of `Inline::<dyn std::fmt::Debug>::{constant#0}` failed
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
    |
 LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |     |
-   |     size_of called on unsized type `dyn Debug`
-   |     inside `std::mem::size_of::<dyn Debug>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ size_of called on unsized type `dyn Debug`
+   |
+note: inside `std::mem::size_of::<dyn Debug>`
+  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
    |
-  ::: $DIR/issue-80742.rs:14:10
+LL |     intrinsics::size_of::<T>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `Inline::<dyn Debug>::{constant#0}`
+  --> $DIR/issue-80742.rs:14:10
    |
 LL |     [u8; size_of::<T>() + 1]: ,
-   |          -------------- inside `Inline::<dyn Debug>::{constant#0}` at $DIR/issue-80742.rs:14:10
+   |          ^^^^^^^^^^^^^^
 
 error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time
   --> $DIR/issue-80742.rs:30:15
diff --git a/src/test/ui/const-generics/issues/issue-100313.stderr b/src/test/ui/const-generics/issues/issue-100313.stderr
index f3ce357c2bb..d4b486376ca 100644
--- a/src/test/ui/const-generics/issues/issue-100313.stderr
+++ b/src/test/ui/const-generics/issues/issue-100313.stderr
@@ -2,13 +2,18 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/issue-100313.rs:10:13
    |
 LL |             *(B as *const bool as *mut bool) = false;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ writing to alloc7 which is read-only
+   |
+note: inside `T::<&true>::set_false`
+  --> $DIR/issue-100313.rs:10:13
+   |
+LL |             *(B as *const bool as *mut bool) = false;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |             |
-   |             writing to alloc7 which is read-only
-   |             inside `T::<&true>::set_false` at $DIR/issue-100313.rs:10:13
-...
+note: inside `_`
+  --> $DIR/issue-100313.rs:18:5
+   |
 LL |     x.set_false();
-   |     ------------- inside `_` at $DIR/issue-100313.rs:18:5
+   |     ^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-ptr/forbidden_slices.32bit.stderr b/src/test/ui/const-ptr/forbidden_slices.32bit.stderr
index 8978ab436d0..563f3ffd674 100644
--- a/src/test/ui/const-ptr/forbidden_slices.32bit.stderr
+++ b/src/test/ui/const-ptr/forbidden_slices.32bit.stderr
@@ -2,43 +2,52 @@ error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
 LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
-   |         inside `std::slice::from_raw_parts::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
+   |
+note: inside `std::slice::from_raw_parts::<'_, u32>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-  ::: $DIR/forbidden_slices.rs:18:34
+LL |         &*ptr::slice_from_raw_parts(data, len)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `S0`
+  --> $DIR/forbidden_slices.rs:18:34
    |
 LL | pub static S0: &[u32] = unsafe { from_raw_parts(ptr::null(), 0) };
-   |                                  ------------------------------ inside `S0` at $DIR/forbidden_slices.rs:18:34
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
 LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
-   |         inside `std::slice::from_raw_parts::<'_, ()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
+   |
+note: inside `std::slice::from_raw_parts::<'_, ()>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-  ::: $DIR/forbidden_slices.rs:19:33
+LL |         &*ptr::slice_from_raw_parts(data, len)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `S1`
+  --> $DIR/forbidden_slices.rs:19:33
    |
 LL | pub static S1: &[()] = unsafe { from_raw_parts(ptr::null(), 0) };
-   |                                 ------------------------------ inside `S1` at $DIR/forbidden_slices.rs:19:33
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
 LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         dereferencing pointer failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
-   |         inside `std::slice::from_raw_parts::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+   |
+note: inside `std::slice::from_raw_parts::<'_, u32>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-  ::: $DIR/forbidden_slices.rs:22:34
+LL |         &*ptr::slice_from_raw_parts(data, len)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `S2`
+  --> $DIR/forbidden_slices.rs:22:34
    |
 LL | pub static S2: &[u32] = unsafe { from_raw_parts(&D0, 2) };
-   |                                  ---------------------- inside `S2` at $DIR/forbidden_slices.rs:22:34
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/forbidden_slices.rs:25:1
@@ -89,72 +98,85 @@ error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
 LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         dereferencing pointer failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
-   |         inside `std::slice::from_raw_parts::<'_, u64>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
    |
-  ::: $DIR/forbidden_slices.rs:43:5
+note: inside `std::slice::from_raw_parts::<'_, u64>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+LL |         &*ptr::slice_from_raw_parts(data, len)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `S8`
+  --> $DIR/forbidden_slices.rs:43:5
    |
 LL |     from_raw_parts(ptr, 1)
-   |     ---------------------- inside `S8` at $DIR/forbidden_slices.rs:43:5
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
-   |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
    |
-  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `from_ptr_range::<'_, u32>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-  ::: $DIR/forbidden_slices.rs:46:34
+LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `R0`
+  --> $DIR/forbidden_slices.rs:46:34
    |
 LL | pub static R0: &[u32] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
-   |                                  ---------------------------------------- inside `R0` at $DIR/forbidden_slices.rs:46:34
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |         inside `ptr::const_ptr::<impl *const ()>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const ()>::sub_ptr`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ------------------------------ inside `from_ptr_range::<'_, ()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+LL |         assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `from_ptr_range::<'_, ()>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-  ::: $DIR/forbidden_slices.rs:47:33
+LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `R1`
+  --> $DIR/forbidden_slices.rs:47:33
    |
 LL | pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
-   |                                 ---------------------------------------- inside `R1` at $DIR/forbidden_slices.rs:47:33
-   |
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+   |
+note: inside `ptr::const_ptr::<impl *const u32>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::offset(self, count) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
-   |                  inside `ptr::const_ptr::<impl *const u32>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-...
-LL |         unsafe { self.offset(count as isize) }
-   |                  --------------------------- inside `ptr::const_ptr::<impl *const u32>::add` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::add`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/forbidden_slices.rs:50:25
+LL |         unsafe { self.offset(count as isize) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `R2`
+  --> $DIR/forbidden_slices.rs:50:25
    |
 LL |     from_ptr_range(ptr..ptr.add(2))
-   |                         ---------- inside `R2` at $DIR/forbidden_slices.rs:50:25
+   |                         ^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/forbidden_slices.rs:52:1
@@ -205,56 +227,67 @@ error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
+   |
+note: inside `ptr::const_ptr::<impl *const u64>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::offset(self, count) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
-   |                  inside `ptr::const_ptr::<impl *const u64>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-...
-LL |         unsafe { self.offset(count as isize) }
-   |                  --------------------------- inside `ptr::const_ptr::<impl *const u64>::add` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u64>::add`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/forbidden_slices.rs:74:25
+LL |         unsafe { self.offset(count as isize) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `R8`
+  --> $DIR/forbidden_slices.rs:74:25
    |
 LL |     from_ptr_range(ptr..ptr.add(1))
-   |                         ---------- inside `R8` at $DIR/forbidden_slices.rs:74:25
+   |                         ^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  `ptr_offset_from_unsigned` called on pointers into different allocations
-   |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on pointers into different allocations
    |
-  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `from_ptr_range::<'_, u32>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-  ::: $DIR/forbidden_slices.rs:79:34
+LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `R9`
+  --> $DIR/forbidden_slices.rs:79:34
    |
 LL | pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).add(1)) };
-   |                                  ----------------------------------------------- inside `R9` at $DIR/forbidden_slices.rs:79:34
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  `ptr_offset_from_unsigned` called on pointers into different allocations
-   |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on pointers into different allocations
    |
-  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `from_ptr_range::<'_, u32>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-  ::: $DIR/forbidden_slices.rs:80:35
+LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `R10`
+  --> $DIR/forbidden_slices.rs:80:35
    |
 LL | pub static R10: &[u32] = unsafe { from_ptr_range(&D0..&D0) };
-   |                                   ------------------------ inside `R10` at $DIR/forbidden_slices.rs:80:35
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 18 previous errors
 
diff --git a/src/test/ui/const-ptr/forbidden_slices.64bit.stderr b/src/test/ui/const-ptr/forbidden_slices.64bit.stderr
index db42b7c9830..43529d57f40 100644
--- a/src/test/ui/const-ptr/forbidden_slices.64bit.stderr
+++ b/src/test/ui/const-ptr/forbidden_slices.64bit.stderr
@@ -2,43 +2,52 @@ error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
 LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
-   |         inside `std::slice::from_raw_parts::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
+   |
+note: inside `std::slice::from_raw_parts::<'_, u32>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-  ::: $DIR/forbidden_slices.rs:18:34
+LL |         &*ptr::slice_from_raw_parts(data, len)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `S0`
+  --> $DIR/forbidden_slices.rs:18:34
    |
 LL | pub static S0: &[u32] = unsafe { from_raw_parts(ptr::null(), 0) };
-   |                                  ------------------------------ inside `S0` at $DIR/forbidden_slices.rs:18:34
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
 LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
-   |         inside `std::slice::from_raw_parts::<'_, ()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: null pointer is a dangling pointer (it has no provenance)
+   |
+note: inside `std::slice::from_raw_parts::<'_, ()>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-  ::: $DIR/forbidden_slices.rs:19:33
+LL |         &*ptr::slice_from_raw_parts(data, len)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `S1`
+  --> $DIR/forbidden_slices.rs:19:33
    |
 LL | pub static S1: &[()] = unsafe { from_raw_parts(ptr::null(), 0) };
-   |                                 ------------------------------ inside `S1` at $DIR/forbidden_slices.rs:19:33
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
 LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         dereferencing pointer failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
-   |         inside `std::slice::from_raw_parts::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+   |
+note: inside `std::slice::from_raw_parts::<'_, u32>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-  ::: $DIR/forbidden_slices.rs:22:34
+LL |         &*ptr::slice_from_raw_parts(data, len)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `S2`
+  --> $DIR/forbidden_slices.rs:22:34
    |
 LL | pub static S2: &[u32] = unsafe { from_raw_parts(&D0, 2) };
-   |                                  ---------------------- inside `S2` at $DIR/forbidden_slices.rs:22:34
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/forbidden_slices.rs:25:1
@@ -89,72 +98,85 @@ error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
 LL |         &*ptr::slice_from_raw_parts(data, len)
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         dereferencing pointer failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
-   |         inside `std::slice::from_raw_parts::<'_, u64>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
    |
-  ::: $DIR/forbidden_slices.rs:43:5
+note: inside `std::slice::from_raw_parts::<'_, u64>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
+   |
+LL |         &*ptr::slice_from_raw_parts(data, len)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `S8`
+  --> $DIR/forbidden_slices.rs:43:5
    |
 LL |     from_raw_parts(ptr, 1)
-   |     ---------------------- inside `S8` at $DIR/forbidden_slices.rs:43:5
+   |     ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
-   |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
    |
-  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `from_ptr_range::<'_, u32>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-  ::: $DIR/forbidden_slices.rs:46:34
+LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `R0`
+  --> $DIR/forbidden_slices.rs:46:34
    |
 LL | pub static R0: &[u32] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
-   |                                  ---------------------------------------- inside `R0` at $DIR/forbidden_slices.rs:46:34
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-   |         inside `ptr::const_ptr::<impl *const ()>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: 0 < pointee_size && pointee_size <= isize::MAX as usize', $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const ()>::sub_ptr`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ------------------------------ inside `from_ptr_range::<'_, ()>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+LL |         assert!(0 < pointee_size && pointee_size <= isize::MAX as usize);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `from_ptr_range::<'_, ()>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-  ::: $DIR/forbidden_slices.rs:47:33
+LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `R1`
+  --> $DIR/forbidden_slices.rs:47:33
    |
 LL | pub static R1: &[()] = unsafe { from_ptr_range(ptr::null()..ptr::null()) };
-   |                                 ---------------------------------------- inside `R1` at $DIR/forbidden_slices.rs:47:33
-   |
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
+   |
+note: inside `ptr::const_ptr::<impl *const u32>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::offset(self, count) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: ALLOC_ID has size 4, so pointer to 8 bytes starting at offset 0 is out-of-bounds
-   |                  inside `ptr::const_ptr::<impl *const u32>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-...
-LL |         unsafe { self.offset(count as isize) }
-   |                  --------------------------- inside `ptr::const_ptr::<impl *const u32>::add` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::add`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/forbidden_slices.rs:50:25
+LL |         unsafe { self.offset(count as isize) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `R2`
+  --> $DIR/forbidden_slices.rs:50:25
    |
 LL |     from_ptr_range(ptr..ptr.add(2))
-   |                         ---------- inside `R2` at $DIR/forbidden_slices.rs:50:25
+   |                         ^^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/forbidden_slices.rs:52:1
@@ -205,56 +227,67 @@ error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
+   |
+note: inside `ptr::const_ptr::<impl *const u64>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::offset(self, count) }
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: ALLOC_ID has size 8, so pointer to 8 bytes starting at offset 1 is out-of-bounds
-   |                  inside `ptr::const_ptr::<impl *const u64>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
-...
-LL |         unsafe { self.offset(count as isize) }
-   |                  --------------------------- inside `ptr::const_ptr::<impl *const u64>::add` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u64>::add`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/forbidden_slices.rs:74:25
+LL |         unsafe { self.offset(count as isize) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `R8`
+  --> $DIR/forbidden_slices.rs:74:25
    |
 LL |     from_ptr_range(ptr..ptr.add(1))
-   |                         ---------- inside `R8` at $DIR/forbidden_slices.rs:74:25
+   |                         ^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  `ptr_offset_from_unsigned` called on pointers into different allocations
-   |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on pointers into different allocations
    |
-  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `from_ptr_range::<'_, u32>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-  ::: $DIR/forbidden_slices.rs:79:34
+LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `R9`
+  --> $DIR/forbidden_slices.rs:79:34
    |
 LL | pub static R9: &[u32] = unsafe { from_ptr_range(&D0..(&D0 as *const u32).add(1)) };
-   |                                  ----------------------------------------------- inside `R9` at $DIR/forbidden_slices.rs:79:34
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  `ptr_offset_from_unsigned` called on pointers into different allocations
-   |                  inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on pointers into different allocations
    |
-  ::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
+note: inside `ptr::const_ptr::<impl *const u32>::sub_ptr`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
-   |                                          ------------------------------ inside `from_ptr_range::<'_, u32>` at $SRC_DIR/core/src/slice/raw.rs:LL:COL
+LL |         unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `from_ptr_range::<'_, u32>`
+  --> $SRC_DIR/core/src/slice/raw.rs:LL:COL
    |
-  ::: $DIR/forbidden_slices.rs:80:35
+LL |     unsafe { from_raw_parts(range.start, range.end.sub_ptr(range.start)) }
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `R10`
+  --> $DIR/forbidden_slices.rs:80:35
    |
 LL | pub static R10: &[u32] = unsafe { from_ptr_range(&D0..&D0) };
-   |                                   ------------------------ inside `R10` at $DIR/forbidden_slices.rs:80:35
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 18 previous errors
 
diff --git a/src/test/ui/const-ptr/out_of_bounds_read.stderr b/src/test/ui/const-ptr/out_of_bounds_read.stderr
index 52b173c4d04..bca29b46881 100644
--- a/src/test/ui/const-ptr/out_of_bounds_read.stderr
+++ b/src/test/ui/const-ptr/out_of_bounds_read.stderr
@@ -2,53 +2,62 @@ error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
 LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
-   |         inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   |
+note: inside `std::ptr::read::<u32>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-  ::: $DIR/out_of_bounds_read.rs:12:33
+LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `_READ`
+  --> $DIR/out_of_bounds_read.rs:12:33
    |
 LL |     const _READ: u32 = unsafe { ptr::read(PAST_END_PTR) };
-   |                                 ----------------------- inside `_READ` at $DIR/out_of_bounds_read.rs:12:33
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
 LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
-   |         inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
    |
-  ::: $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `std::ptr::read::<u32>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-LL |         unsafe { read(self) }
-   |                  ---------- inside `ptr::const_ptr::<impl *const u32>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `ptr::const_ptr::<impl *const u32>::read`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/out_of_bounds_read.rs:13:39
+LL |         unsafe { read(self) }
+   |                  ^^^^^^^^^^
+note: inside `_CONST_READ`
+  --> $DIR/out_of_bounds_read.rs:13:39
    |
 LL |     const _CONST_READ: u32 = unsafe { PAST_END_PTR.read() };
-   |                                       ------------------- inside `_CONST_READ` at $DIR/out_of_bounds_read.rs:13:39
+   |                                       ^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
 LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
-   |         inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: alloc5 has size 4, so pointer to 4 bytes starting at offset 4 is out-of-bounds
+   |
+note: inside `std::ptr::read::<u32>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-  ::: $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `ptr::mut_ptr::<impl *mut u32>::read`
+  --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
    |
 LL |         unsafe { read(self) }
-   |                  ---------- inside `ptr::mut_ptr::<impl *mut u32>::read` at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
-   |
-  ::: $DIR/out_of_bounds_read.rs:14:37
+   |                  ^^^^^^^^^^
+note: inside `_MUT_READ`
+  --> $DIR/out_of_bounds_read.rs:14:37
    |
 LL |     const _MUT_READ: u32 = unsafe { (PAST_END_PTR as *mut u32).read() };
-   |                                     --------------------------------- inside `_MUT_READ` at $DIR/out_of_bounds_read.rs:14:37
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
index 3784a3861c3..0734f479f98 100644
--- a/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
+++ b/src/test/ui/consts/const-eval/const_fn_ptr_fail2.stderr
@@ -2,25 +2,35 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/const_fn_ptr_fail2.rs:9:5
    |
 LL |     x(y)
+   |     ^^^^ calling non-const function `double`
+   |
+note: inside `bar`
+  --> $DIR/const_fn_ptr_fail2.rs:9:5
+   |
+LL |     x(y)
    |     ^^^^
-   |     |
-   |     calling non-const function `double`
-   |     inside `bar` at $DIR/const_fn_ptr_fail2.rs:9:5
-...
+note: inside `Y`
+  --> $DIR/const_fn_ptr_fail2.rs:14:18
+   |
 LL | const Y: usize = bar(X, 2); // FIXME: should fail to typeck someday
-   |                  --------- inside `Y` at $DIR/const_fn_ptr_fail2.rs:14:18
+   |                  ^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/const_fn_ptr_fail2.rs:9:5
    |
 LL |     x(y)
+   |     ^^^^ calling non-const function `double`
+   |
+note: inside `bar`
+  --> $DIR/const_fn_ptr_fail2.rs:9:5
+   |
+LL |     x(y)
    |     ^^^^
-   |     |
-   |     calling non-const function `double`
-   |     inside `bar` at $DIR/const_fn_ptr_fail2.rs:9:5
-...
+note: inside `Z`
+  --> $DIR/const_fn_ptr_fail2.rs:15:18
+   |
 LL | const Z: usize = bar(double, 2); // FIXME: should fail to typeck someday
-   |                  -------------- inside `Z` at $DIR/const_fn_ptr_fail2.rs:15:18
+   |                  ^^^^^^^^^^^^^^
 
 warning: skipping const checks
    |
diff --git a/src/test/ui/consts/const-eval/const_panic_track_caller.stderr b/src/test/ui/consts/const-eval/const_panic_track_caller.stderr
index 5c3b412d37f..846458176d6 100644
--- a/src/test/ui/consts/const-eval/const_panic_track_caller.stderr
+++ b/src/test/ui/consts/const-eval/const_panic_track_caller.stderr
@@ -2,13 +2,18 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/const_panic_track_caller.rs:15:5
    |
 LL |     b()
+   |     ^^^ the evaluated program panicked at 'hey', $DIR/const_panic_track_caller.rs:15:5
+   |
+note: inside `c`
+  --> $DIR/const_panic_track_caller.rs:15:5
+   |
+LL |     b()
    |     ^^^
-   |     |
-   |     the evaluated program panicked at 'hey', $DIR/const_panic_track_caller.rs:15:5
-   |     inside `c` at $DIR/const_panic_track_caller.rs:15:5
-...
+note: inside `X`
+  --> $DIR/const_panic_track_caller.rs:21:16
+   |
 LL | const X: u32 = c();
-   |                --- inside `X` at $DIR/const_panic_track_caller.rs:21:16
+   |                ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr
index 2628a78455c..8f3b3d5f700 100644
--- a/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr
+++ b/src/test/ui/consts/const-eval/heap/alloc_intrinsic_errors.stderr
@@ -1,14 +1,19 @@
 error[E0080]: evaluation of constant value failed
   --> $DIR/alloc_intrinsic_errors.rs:9:17
    |
-LL | const FOO: i32 = foo();
-   |                  ----- inside `FOO` at $DIR/alloc_intrinsic_errors.rs:6:18
-...
+LL |         let _ = intrinsics::const_allocate(4, 3) as *mut i32;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ align has to be a power of 2, `3` is not a power of 2
+   |
+note: inside `foo`
+  --> $DIR/alloc_intrinsic_errors.rs:9:17
+   |
 LL |         let _ = intrinsics::const_allocate(4, 3) as *mut i32;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                 |
-   |                 align has to be a power of 2, `3` is not a power of 2
-   |                 inside `foo` at $DIR/alloc_intrinsic_errors.rs:9:17
+note: inside `FOO`
+  --> $DIR/alloc_intrinsic_errors.rs:6:18
+   |
+LL | const FOO: i32 = foo();
+   |                  ^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/const-eval/unwind-abort.stderr b/src/test/ui/consts/const-eval/unwind-abort.stderr
index 99178ae8c83..759ce15ab1b 100644
--- a/src/test/ui/consts/const-eval/unwind-abort.stderr
+++ b/src/test/ui/consts/const-eval/unwind-abort.stderr
@@ -2,14 +2,18 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/unwind-abort.rs:4:5
    |
 LL |     panic!()
+   |     ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/unwind-abort.rs:4:5
+   |
+note: inside `foo`
+  --> $DIR/unwind-abort.rs:4:5
+   |
+LL |     panic!()
    |     ^^^^^^^^
-   |     |
-   |     the evaluated program panicked at 'explicit panic', $DIR/unwind-abort.rs:4:5
-   |     inside `foo` at $SRC_DIR/std/src/panic.rs:LL:COL
-...
-LL | const _: () = foo();
-   |               ----- inside `_` at $DIR/unwind-abort.rs:7:15
+note: inside `_`
+  --> $DIR/unwind-abort.rs:7:15
    |
+LL | const _: () = foo();
+   |               ^^^^^
    = 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
diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
index 8b4d845b30e..9710bf476ec 100644
--- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
+++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.32bit.stderr
@@ -14,13 +14,18 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/validate_uninhabited_zsts.rs:4:14
    |
 LL |     unsafe { std::mem::transmute(()) }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
+   |
+note: inside `foo`
+  --> $DIR/validate_uninhabited_zsts.rs:4:14
+   |
+LL |     unsafe { std::mem::transmute(()) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^
-   |              |
-   |              transmuting to uninhabited type
-   |              inside `foo` at $DIR/validate_uninhabited_zsts.rs:4:14
-...
+note: inside `FOO`
+  --> $DIR/validate_uninhabited_zsts.rs:19:33
+   |
 LL | const FOO: [empty::Empty; 3] = [foo(); 3];
-   |                                 ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:19:33
+   |                                 ^^^^^
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/validate_uninhabited_zsts.rs:21:1
diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
index 8b4d845b30e..9710bf476ec 100644
--- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
+++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.64bit.stderr
@@ -14,13 +14,18 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/validate_uninhabited_zsts.rs:4:14
    |
 LL |     unsafe { std::mem::transmute(()) }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^ transmuting to uninhabited type
+   |
+note: inside `foo`
+  --> $DIR/validate_uninhabited_zsts.rs:4:14
+   |
+LL |     unsafe { std::mem::transmute(()) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^
-   |              |
-   |              transmuting to uninhabited type
-   |              inside `foo` at $DIR/validate_uninhabited_zsts.rs:4:14
-...
+note: inside `FOO`
+  --> $DIR/validate_uninhabited_zsts.rs:19:33
+   |
 LL | const FOO: [empty::Empty; 3] = [foo(); 3];
-   |                                 ----- inside `FOO` at $DIR/validate_uninhabited_zsts.rs:19:33
+   |                                 ^^^^^
 
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/validate_uninhabited_zsts.rs:21:1
diff --git a/src/test/ui/consts/const-float-bits-reject-conv.stderr b/src/test/ui/consts/const-float-bits-reject-conv.stderr
index e1ad72416f2..195a087ffa5 100644
--- a/src/test/ui/consts/const-float-bits-reject-conv.stderr
+++ b/src/test/ui/consts/const-float-bits-reject-conv.stderr
@@ -2,38 +2,46 @@ error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/num/f32.rs:LL:COL
    |
 LL |                     panic!("const-eval error: cannot use f32::to_bits on a NaN")
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
+   |
+note: inside `core::f32::<impl f32>::to_bits::ct_f32_to_u32`
+  --> $SRC_DIR/core/src/num/f32.rs:LL:COL
+   |
+LL |                     panic!("const-eval error: cannot use f32::to_bits on a NaN")
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                     |
-   |                     the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
-   |                     inside `core::f32::<impl f32>::to_bits::ct_f32_to_u32` at $SRC_DIR/core/src/panic.rs:LL:COL
-...
-LL |         unsafe { intrinsics::const_eval_select((self,), ct_f32_to_u32, rt_f32_to_u32) }
-   |                  -------------------------------------------------------------------- inside `core::f32::<impl f32>::to_bits` at $SRC_DIR/core/src/num/f32.rs:LL:COL
+note: inside `core::f32::<impl f32>::to_bits`
+  --> $SRC_DIR/core/src/num/f32.rs:LL:COL
    |
-  ::: $DIR/const-float-bits-reject-conv.rs:28:30
+LL |         unsafe { intrinsics::const_eval_select((self,), ct_f32_to_u32, rt_f32_to_u32) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `f32::MASKED_NAN1`
+  --> $DIR/const-float-bits-reject-conv.rs:28:30
    |
 LL |     const MASKED_NAN1: u32 = f32::NAN.to_bits() ^ 0x002A_AAAA;
-   |                              ------------------ inside `f32::MASKED_NAN1` at $DIR/const-float-bits-reject-conv.rs:28:30
-   |
+   |                              ^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/num/f32.rs:LL:COL
    |
 LL |                     panic!("const-eval error: cannot use f32::to_bits on a NaN")
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
+   |
+note: inside `core::f32::<impl f32>::to_bits::ct_f32_to_u32`
+  --> $SRC_DIR/core/src/num/f32.rs:LL:COL
+   |
+LL |                     panic!("const-eval error: cannot use f32::to_bits on a NaN")
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                     |
-   |                     the evaluated program panicked at 'const-eval error: cannot use f32::to_bits on a NaN', $SRC_DIR/core/src/num/f32.rs:LL:COL
-   |                     inside `core::f32::<impl f32>::to_bits::ct_f32_to_u32` at $SRC_DIR/core/src/panic.rs:LL:COL
-...
-LL |         unsafe { intrinsics::const_eval_select((self,), ct_f32_to_u32, rt_f32_to_u32) }
-   |                  -------------------------------------------------------------------- inside `core::f32::<impl f32>::to_bits` at $SRC_DIR/core/src/num/f32.rs:LL:COL
+note: inside `core::f32::<impl f32>::to_bits`
+  --> $SRC_DIR/core/src/num/f32.rs:LL:COL
    |
-  ::: $DIR/const-float-bits-reject-conv.rs:30:30
+LL |         unsafe { intrinsics::const_eval_select((self,), ct_f32_to_u32, rt_f32_to_u32) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `f32::MASKED_NAN2`
+  --> $DIR/const-float-bits-reject-conv.rs:30:30
    |
 LL |     const MASKED_NAN2: u32 = f32::NAN.to_bits() ^ 0x0055_5555;
-   |                              ------------------ inside `f32::MASKED_NAN2` at $DIR/const-float-bits-reject-conv.rs:30:30
-   |
+   |                              ^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: erroneous constant used
@@ -64,38 +72,46 @@ error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/num/f64.rs:LL:COL
    |
 LL |                     panic!("const-eval error: cannot use f64::to_bits on a NaN")
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
+   |
+note: inside `core::f64::<impl f64>::to_bits::ct_f64_to_u64`
+  --> $SRC_DIR/core/src/num/f64.rs:LL:COL
+   |
+LL |                     panic!("const-eval error: cannot use f64::to_bits on a NaN")
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                     |
-   |                     the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
-   |                     inside `core::f64::<impl f64>::to_bits::ct_f64_to_u64` at $SRC_DIR/core/src/panic.rs:LL:COL
-...
-LL |         unsafe { intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64) }
-   |                  -------------------------------------------------------------------- inside `core::f64::<impl f64>::to_bits` at $SRC_DIR/core/src/num/f64.rs:LL:COL
+note: inside `core::f64::<impl f64>::to_bits`
+  --> $SRC_DIR/core/src/num/f64.rs:LL:COL
    |
-  ::: $DIR/const-float-bits-reject-conv.rs:50:30
+LL |         unsafe { intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `f64::MASKED_NAN1`
+  --> $DIR/const-float-bits-reject-conv.rs:50:30
    |
 LL |     const MASKED_NAN1: u64 = f64::NAN.to_bits() ^ 0x000A_AAAA_AAAA_AAAA;
-   |                              ------------------ inside `f64::MASKED_NAN1` at $DIR/const-float-bits-reject-conv.rs:50:30
-   |
+   |                              ^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/num/f64.rs:LL:COL
    |
 LL |                     panic!("const-eval error: cannot use f64::to_bits on a NaN")
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
+   |
+note: inside `core::f64::<impl f64>::to_bits::ct_f64_to_u64`
+  --> $SRC_DIR/core/src/num/f64.rs:LL:COL
+   |
+LL |                     panic!("const-eval error: cannot use f64::to_bits on a NaN")
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                     |
-   |                     the evaluated program panicked at 'const-eval error: cannot use f64::to_bits on a NaN', $SRC_DIR/core/src/num/f64.rs:LL:COL
-   |                     inside `core::f64::<impl f64>::to_bits::ct_f64_to_u64` at $SRC_DIR/core/src/panic.rs:LL:COL
-...
-LL |         unsafe { intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64) }
-   |                  -------------------------------------------------------------------- inside `core::f64::<impl f64>::to_bits` at $SRC_DIR/core/src/num/f64.rs:LL:COL
+note: inside `core::f64::<impl f64>::to_bits`
+  --> $SRC_DIR/core/src/num/f64.rs:LL:COL
    |
-  ::: $DIR/const-float-bits-reject-conv.rs:52:30
+LL |         unsafe { intrinsics::const_eval_select((self,), ct_f64_to_u64, rt_f64_to_u64) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `f64::MASKED_NAN2`
+  --> $DIR/const-float-bits-reject-conv.rs:52:30
    |
 LL |     const MASKED_NAN2: u64 = f64::NAN.to_bits() ^ 0x0005_5555_5555_5555;
-   |                              ------------------ inside `f64::MASKED_NAN2` at $DIR/const-float-bits-reject-conv.rs:52:30
-   |
+   |                              ^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: erroneous constant used
diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr
index 234e55e3a96..6e110dbdd64 100644
--- a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr
+++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr
@@ -2,13 +2,18 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/mut_ref_in_final_dynamic_check.rs:13:10
    |
 LL |     Some(&mut *(42 as *mut i32))
+   |          ^^^^^^^^^^^^^^^^^^^^^^ dereferencing pointer failed: 0x2a[noalloc] is a dangling pointer (it has no provenance)
+   |
+note: inside `helper`
+  --> $DIR/mut_ref_in_final_dynamic_check.rs:13:10
+   |
+LL |     Some(&mut *(42 as *mut i32))
    |          ^^^^^^^^^^^^^^^^^^^^^^
-   |          |
-   |          dereferencing pointer failed: 0x2a[noalloc] is a dangling pointer (it has no provenance)
-   |          inside `helper` at $DIR/mut_ref_in_final_dynamic_check.rs:13:10
-...
+note: inside `A`
+  --> $DIR/mut_ref_in_final_dynamic_check.rs:18:29
+   |
 LL | const A: Option<&mut i32> = helper();
-   |                             -------- inside `A` at $DIR/mut_ref_in_final_dynamic_check.rs:18:29
+   |                             ^^^^^^^^
 
 error: encountered dangling pointer in final constant
   --> $DIR/mut_ref_in_final_dynamic_check.rs:25:1
diff --git a/src/test/ui/consts/const_unsafe_unreachable_ub.stderr b/src/test/ui/consts/const_unsafe_unreachable_ub.stderr
index f6de3699f77..cbc7cac937a 100644
--- a/src/test/ui/consts/const_unsafe_unreachable_ub.stderr
+++ b/src/test/ui/consts/const_unsafe_unreachable_ub.stderr
@@ -2,18 +2,23 @@ error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/hint.rs:LL:COL
    |
 LL |         intrinsics::unreachable()
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         entering unreachable code
-   |         inside `unreachable_unchecked` at $SRC_DIR/core/src/hint.rs:LL:COL
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ entering unreachable code
+   |
+note: inside `unreachable_unchecked`
+  --> $SRC_DIR/core/src/hint.rs:LL:COL
    |
-  ::: $DIR/const_unsafe_unreachable_ub.rs:6:18
+LL |         intrinsics::unreachable()
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `foo`
+  --> $DIR/const_unsafe_unreachable_ub.rs:6:18
    |
 LL |         false => std::hint::unreachable_unchecked(),
-   |                  ---------------------------------- inside `foo` at $DIR/const_unsafe_unreachable_ub.rs:6:18
-...
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `BAR`
+  --> $DIR/const_unsafe_unreachable_ub.rs:10:28
+   |
 LL | const BAR: bool = unsafe { foo(false) };
-   |                            ---------- inside `BAR` at $DIR/const_unsafe_unreachable_ub.rs:10:28
+   |                            ^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr b/src/test/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
index 4726905ade3..2603a73583e 100644
--- a/src/test/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
+++ b/src/test/ui/consts/extra-const-ub/detect-extra-ub.with_flag.stderr
@@ -32,20 +32,23 @@ error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
 LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         accessing memory with alignment 1, but alignment 4 is required
-   |         inside `std::ptr::read::<u32>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ accessing memory with alignment 1, but alignment 4 is required
    |
-  ::: $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+note: inside `std::ptr::read::<u32>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-LL |         unsafe { read(self) }
-   |                  ---------- inside `ptr::const_ptr::<impl *const u32>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `ptr::const_ptr::<impl *const u32>::read`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/detect-extra-ub.rs:38:9
+LL |         unsafe { read(self) }
+   |                  ^^^^^^^^^^
+note: inside `INNER`
+  --> $DIR/detect-extra-ub.rs:38:9
    |
 LL |         ptr.read();
-   |         ---------- inside `INNER` at $DIR/detect-extra-ub.rs:38:9
+   |         ^^^^^^^^^^
 
 note: erroneous constant used
   --> $DIR/detect-extra-ub.rs:32:5
diff --git a/src/test/ui/consts/issue-miri-1910.stderr b/src/test/ui/consts/issue-miri-1910.stderr
index 3872e3d4f0d..1f82e1777af 100644
--- a/src/test/ui/consts/issue-miri-1910.stderr
+++ b/src/test/ui/consts/issue-miri-1910.stderr
@@ -2,23 +2,25 @@ error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
 LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |         |
-   |         unable to copy parts of a pointer from memory at ALLOC
-   |         inside `std::ptr::read::<u8>` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unable to copy parts of a pointer from memory at ALLOC
    |
-  ::: $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   = help: this code performed an operation that depends on the underlying bytes representing a pointer
+   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
+note: inside `std::ptr::read::<u8>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-LL |         unsafe { read(self) }
-   |                  ---------- inside `ptr::const_ptr::<impl *const u8>::read` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+LL |         copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `ptr::const_ptr::<impl *const u8>::read`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/issue-miri-1910.rs:8:5
+LL |         unsafe { read(self) }
+   |                  ^^^^^^^^^^
+note: inside `C`
+  --> $DIR/issue-miri-1910.rs:8:5
    |
 LL |     (&foo as *const _ as *const u8).add(one_and_a_half_pointers).read();
-   |     ------------------------------------------------------------------- inside `C` at $DIR/issue-miri-1910.rs:8:5
-   |
-   = help: this code performed an operation that depends on the underlying bytes representing a pointer
-   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr b/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr
index 840d698ebbf..cf3fd88d034 100644
--- a/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr
+++ b/src/test/ui/consts/miri_unleashed/abi-mismatch.stderr
@@ -2,13 +2,18 @@ error[E0080]: could not evaluate static initializer
   --> $DIR/abi-mismatch.rs:9:5
    |
 LL |     my_fn();
+   |     ^^^^^^^ calling a function with calling convention C using calling convention Rust
+   |
+note: inside `call_rust_fn`
+  --> $DIR/abi-mismatch.rs:9:5
+   |
+LL |     my_fn();
    |     ^^^^^^^
-   |     |
-   |     calling a function with calling convention C using calling convention Rust
-   |     inside `call_rust_fn` at $DIR/abi-mismatch.rs:9:5
-...
+note: inside `VAL`
+  --> $DIR/abi-mismatch.rs:15:18
+   |
 LL | static VAL: () = call_rust_fn(unsafe { std::mem::transmute(c_fn as extern "C" fn()) });
-   |                  --------------------------------------------------------------------- inside `VAL` at $DIR/abi-mismatch.rs:15:18
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: skipping const checks
    |
diff --git a/src/test/ui/consts/miri_unleashed/assoc_const.stderr b/src/test/ui/consts/miri_unleashed/assoc_const.stderr
index 33e7e4af276..b26f121dba0 100644
--- a/src/test/ui/consts/miri_unleashed/assoc_const.stderr
+++ b/src/test/ui/consts/miri_unleashed/assoc_const.stderr
@@ -2,16 +2,23 @@ error[E0080]: evaluation of `<std::string::String as Bar<std::vec::Vec<u32>, std
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
 LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `<Vec<u32> as Drop>::drop`
+   |
+note: inside `std::ptr::drop_in_place::<Vec<u32>> - shim(Some(Vec<u32>))`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |
+LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
-   | calling non-const function `<Vec<u32> as Drop>::drop`
-   | inside `std::ptr::drop_in_place::<Vec<u32>> - shim(Some(Vec<u32>))` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
-   | inside `std::ptr::drop_in_place::<(Vec<u32>, u32)> - shim(Some((Vec<u32>, u32)))` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `std::ptr::drop_in_place::<(Vec<u32>, u32)> - shim(Some((Vec<u32>, u32)))`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-  ::: $DIR/assoc_const.rs:12:31
+LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `<String as Bar<Vec<u32>, String>>::F`
+  --> $DIR/assoc_const.rs:12:31
    |
 LL |     const F: u32 = (U::X, 42).1;
-   |                               - inside `<String as Bar<Vec<u32>, String>>::F` at $DIR/assoc_const.rs:12:31
+   |                               ^
 
 note: erroneous constant used
   --> $DIR/assoc_const.rs:29:13
diff --git a/src/test/ui/consts/miri_unleashed/drop.stderr b/src/test/ui/consts/miri_unleashed/drop.stderr
index a3a502723d2..e2e2f16d5a0 100644
--- a/src/test/ui/consts/miri_unleashed/drop.stderr
+++ b/src/test/ui/consts/miri_unleashed/drop.stderr
@@ -2,15 +2,18 @@ error[E0080]: could not evaluate static initializer
   --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
 LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   | |
-   | calling non-const function `<Vec<i32> as Drop>::drop`
-   | inside `std::ptr::drop_in_place::<Vec<i32>> - shim(Some(Vec<i32>))` at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling non-const function `<Vec<i32> as Drop>::drop`
+   |
+note: inside `std::ptr::drop_in_place::<Vec<i32>> - shim(Some(Vec<i32>))`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
    |
-  ::: $DIR/drop.rs:17:1
+LL | pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `TEST_BAD`
+  --> $DIR/drop.rs:17:1
    |
 LL | };
-   | - inside `TEST_BAD` at $DIR/drop.rs:17:1
+   | ^
 
 warning: skipping const checks
    |
diff --git a/src/test/ui/consts/missing_span_in_backtrace.rs b/src/test/ui/consts/missing_span_in_backtrace.rs
new file mode 100644
index 00000000000..c4930b73aaa
--- /dev/null
+++ b/src/test/ui/consts/missing_span_in_backtrace.rs
@@ -0,0 +1,27 @@
+// compile-flags: -Z simulate-remapped-rust-src-base=/rustc/FAKE_PREFIX -Z translate-remapped-path-to-local-path=no -Z ui-testing=no
+// normalize-stderr-test "alloc[0-9]+" -> "ALLOC_ID"
+
+#![feature(const_swap)]
+#![feature(const_mut_refs)]
+use std::{
+    mem::{self, MaybeUninit},
+    ptr,
+};
+
+const X: () = {
+    let mut ptr1 = &1;
+    let mut ptr2 = &2;
+
+    // Swap them, bytewise.
+    unsafe {
+        ptr::swap_nonoverlapping(
+            &mut ptr1 as *mut _ as *mut MaybeUninit<u8>,
+            &mut ptr2 as *mut _ as *mut MaybeUninit<u8>,
+            mem::size_of::<&i32>(),
+        );
+    }
+};
+
+fn main() {
+    X
+}
diff --git a/src/test/ui/consts/missing_span_in_backtrace.stderr b/src/test/ui/consts/missing_span_in_backtrace.stderr
new file mode 100644
index 00000000000..e6d3d51990d
--- /dev/null
+++ b/src/test/ui/consts/missing_span_in_backtrace.stderr
@@ -0,0 +1,28 @@
+error[E0080]: evaluation of constant value failed
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+   |
+   = note: unable to copy parts of a pointer from memory at ALLOC_ID
+   |
+   = help: this code performed an operation that depends on the underlying bytes representing a pointer
+   = help: the absolute address of a pointer is not known at compile-time, so such operations are not supported
+note: inside `std::ptr::read::<MaybeUninit<MaybeUninit<u8>>>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `mem::swap_simple::<MaybeUninit<MaybeUninit<u8>>>`
+  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+note: inside `ptr::swap_nonoverlapping_simple_untyped::<MaybeUninit<u8>>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `swap_nonoverlapping::<MaybeUninit<u8>>`
+  --> $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+note: inside `X`
+  --> $DIR/missing_span_in_backtrace.rs:17:9
+   |
+17 | /         ptr::swap_nonoverlapping(
+18 | |             &mut ptr1 as *mut _ as *mut MaybeUninit<u8>,
+19 | |             &mut ptr2 as *mut _ as *mut MaybeUninit<u8>,
+20 | |             mem::size_of::<&i32>(),
+21 | |         );
+   | |_________^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/offset_from_ub.stderr b/src/test/ui/consts/offset_from_ub.stderr
index 62a087d94d3..9578d90ea9d 100644
--- a/src/test/ui/consts/offset_from_ub.stderr
+++ b/src/test/ui/consts/offset_from_ub.stderr
@@ -8,15 +8,18 @@ error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  `ptr_offset_from` called on pointers into different allocations
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on pointers into different allocations
+   |
+note: inside `ptr::const_ptr::<impl *const u8>::offset_from`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/offset_from_ub.rs:24:14
+LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `NOT_PTR`
+  --> $DIR/offset_from_ub.rs:24:14
    |
 LL |     unsafe { (42 as *const u8).offset_from(&5u8) as usize }
-   |              ----------------------------------- inside `NOT_PTR` at $DIR/offset_from_ub.rs:24:14
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/offset_from_ub.rs:31:14
@@ -88,29 +91,35 @@ error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
    |
-  ::: $DIR/offset_from_ub.rs:115:14
+note: inside `ptr::const_ptr::<impl *const u8>::offset_from`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `OFFSET_VERY_FAR1`
+  --> $DIR/offset_from_ub.rs:115:14
    |
 LL |     unsafe { ptr2.offset_from(ptr1) }
-   |              ---------------------- inside `OFFSET_VERY_FAR1` at $DIR/offset_from_ub.rs:115:14
+   |              ^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
    |
-  ::: $DIR/offset_from_ub.rs:121:14
+note: inside `ptr::const_ptr::<impl *const u8>::offset_from`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::ptr_offset_from(self, origin) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `OFFSET_VERY_FAR2`
+  --> $DIR/offset_from_ub.rs:121:14
    |
 LL |     unsafe { ptr1.offset_from(ptr2.wrapping_offset(1)) }
-   |              ----------------------------------------- inside `OFFSET_VERY_FAR2` at $DIR/offset_from_ub.rs:121:14
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 15 previous errors
 
diff --git a/src/test/ui/consts/offset_ub.stderr b/src/test/ui/consts/offset_ub.stderr
index 5a792bba50c..7938f70a269 100644
--- a/src/test/ui/consts/offset_ub.stderr
+++ b/src/test/ui/consts/offset_ub.stderr
@@ -2,169 +2,205 @@ error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  overflowing in-bounds pointer arithmetic
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing in-bounds pointer arithmetic
+   |
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/offset_ub.rs:7:46
+LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `BEFORE_START`
+  --> $DIR/offset_ub.rs:7:46
    |
 LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) };
-   |                                              ------------------------------ inside `BEFORE_START` at $DIR/offset_ub.rs:7:46
+   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset 0 is out-of-bounds
    |
-  ::: $DIR/offset_ub.rs:8:43
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `AFTER_END`
+  --> $DIR/offset_ub.rs:8:43
    |
 LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) };
-   |                                           ----------------------------- inside `AFTER_END` at $DIR/offset_ub.rs:8:43
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: allocN has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: allocN has size 100, so pointer to 101 bytes starting at offset 0 is out-of-bounds
    |
-  ::: $DIR/offset_ub.rs:9:45
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `AFTER_ARRAY`
+  --> $DIR/offset_ub.rs:9:45
    |
 LL | pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101) };
-   |                                             ------------------------------- inside `AFTER_ARRAY` at $DIR/offset_ub.rs:9:45
+   |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  overflowing in-bounds pointer arithmetic
-   |                  inside `ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing in-bounds pointer arithmetic
+   |
+note: inside `ptr::const_ptr::<impl *const u16>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/offset_ub.rs:11:43
+LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `OVERFLOW`
+  --> $DIR/offset_ub.rs:11:43
    |
 LL | pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MAX) };
-   |                                           ------------------------------------- inside `OVERFLOW` at $DIR/offset_ub.rs:11:43
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  overflowing in-bounds pointer arithmetic
-   |                  inside `ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing in-bounds pointer arithmetic
    |
-  ::: $DIR/offset_ub.rs:12:44
+note: inside `ptr::const_ptr::<impl *const u16>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `UNDERFLOW`
+  --> $DIR/offset_ub.rs:12:44
    |
 LL | pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) };
-   |                                            ------------------------------------- inside `UNDERFLOW` at $DIR/offset_ub.rs:12:44
+   |                                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  overflowing in-bounds pointer arithmetic
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing in-bounds pointer arithmetic
    |
-  ::: $DIR/offset_ub.rs:13:56
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `OVERFLOW_ADDRESS_SPACE`
+  --> $DIR/offset_ub.rs:13:56
    |
 LL | pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *const u8).offset(2) };
-   |                                                        ----------------------------------- inside `OVERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:13:56
+   |                                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  overflowing in-bounds pointer arithmetic
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ overflowing in-bounds pointer arithmetic
+   |
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/offset_ub.rs:14:57
+LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `UNDERFLOW_ADDRESS_SPACE`
+  --> $DIR/offset_ub.rs:14:57
    |
 LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).offset(-2) };
-   |                                                         --------------------------- inside `UNDERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:14:57
+   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: allocN has size 1, so pointer to 2 bytes starting at offset -4 is out-of-bounds
    |
-  ::: $DIR/offset_ub.rs:15:49
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `NEGATIVE_OFFSET`
+  --> $DIR/offset_ub.rs:15:49
    |
 LL | pub const NEGATIVE_OFFSET: *const u8 = unsafe { [0u8; 1].as_ptr().wrapping_offset(-2).offset(-2) };
-   |                                                 ------------------------------------------------ inside `NEGATIVE_OFFSET` at $DIR/offset_ub.rs:15:49
+   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: allocN has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: allocN has size 0, so pointer to 1 byte starting at offset 0 is out-of-bounds
    |
-  ::: $DIR/offset_ub.rs:17:50
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `ZERO_SIZED_ALLOC`
+  --> $DIR/offset_ub.rs:17:50
    |
 LL | pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1) };
-   |                                                  --------------------------- inside `ZERO_SIZED_ALLOC` at $DIR/offset_ub.rs:17:50
+   |                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) as *mut T }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance)
-   |                  inside `ptr::mut_ptr::<impl *mut u8>::offset` at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: 0x1[noalloc] is a dangling pointer (it has no provenance)
+   |
+note: inside `ptr::mut_ptr::<impl *mut u8>::offset`
+  --> $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL
    |
-  ::: $DIR/offset_ub.rs:18:42
+LL |         unsafe { intrinsics::offset(self, count) as *mut T }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `DANGLING`
+  --> $DIR/offset_ub.rs:18:42
    |
 LL | pub const DANGLING: *const u8 = unsafe { ptr::NonNull::<u8>::dangling().as_ptr().offset(4) };
-   |                                          ------------------------------------------------- inside `DANGLING` at $DIR/offset_ub.rs:18:42
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: null pointer is a dangling pointer (it has no provenance)
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: null pointer is a dangling pointer (it has no provenance)
    |
-  ::: $DIR/offset_ub.rs:21:50
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `NULL_OFFSET_ZERO`
+  --> $DIR/offset_ub.rs:21:50
    |
 LL | pub const NULL_OFFSET_ZERO: *const u8 = unsafe { ptr::null::<u8>().offset(0) };
-   |                                                  --------------------------- inside `NULL_OFFSET_ZERO` at $DIR/offset_ub.rs:21:50
+   |                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: 0x7f..f[noalloc] is a dangling pointer (it has no provenance)
-   |                  inside `ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: 0x7f..f[noalloc] is a dangling pointer (it has no provenance)
    |
-  ::: $DIR/offset_ub.rs:24:47
+note: inside `ptr::const_ptr::<impl *const u8>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |
+LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `UNDERFLOW_ABS`
+  --> $DIR/offset_ub.rs:24:47
    |
 LL | pub const UNDERFLOW_ABS: *const u8 = unsafe { (usize::MAX as *const u8).offset(isize::MIN) };
-   |                                               -------------------------------------------- inside `UNDERFLOW_ABS` at $DIR/offset_ub.rs:24:47
+   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 12 previous errors
 
diff --git a/src/test/ui/consts/ptr_comparisons.stderr b/src/test/ui/consts/ptr_comparisons.stderr
index b71964b92c7..274753ef1bc 100644
--- a/src/test/ui/consts/ptr_comparisons.stderr
+++ b/src/test/ui/consts/ptr_comparisons.stderr
@@ -2,15 +2,18 @@ error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
 LL |         unsafe { intrinsics::offset(self, count) }
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |                  |
-   |                  out-of-bounds pointer arithmetic: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds
-   |                  inside `ptr::const_ptr::<impl *const usize>::offset` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer arithmetic: alloc3 has size $WORD, so pointer to $TWO_WORDS bytes starting at offset 0 is out-of-bounds
+   |
+note: inside `ptr::const_ptr::<impl *const usize>::offset`
+  --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
    |
-  ::: $DIR/ptr_comparisons.rs:50:34
+LL |         unsafe { intrinsics::offset(self, count) }
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `_`
+  --> $DIR/ptr_comparisons.rs:50:34
    |
 LL | const _: *const usize = unsafe { (FOO as *const usize).offset(2) };
-   |                                  ------------------------------- inside `_` at $DIR/ptr_comparisons.rs:50:34
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/ptr_comparisons.rs:53:33
diff --git a/src/test/ui/consts/recursive.stderr b/src/test/ui/consts/recursive.stderr
index 14fa3da7ab0..60ce64d2a1e 100644
--- a/src/test/ui/consts/recursive.stderr
+++ b/src/test/ui/consts/recursive.stderr
@@ -13,14 +13,23 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/recursive.rs:4:5
    |
 LL |     f(x);
+   |     ^^^^ reached the configured maximum number of stack frames
+   |
+note: inside `f::<i32>`
+  --> $DIR/recursive.rs:4:5
+   |
+LL |     f(x);
    |     ^^^^
-   |     |
-   |     reached the configured maximum number of stack frames
-   |     inside `f::<i32>` at $DIR/recursive.rs:4:5
-   |     [... 126 additional calls inside `f::<i32>` at $DIR/recursive.rs:4:5 ...]
-...
+note: [... 126 additional calls inside `f::<i32>` ...]
+  --> $DIR/recursive.rs:4:5
+   |
+LL |     f(x);
+   |     ^^^^
+note: inside `X`
+  --> $DIR/recursive.rs:8:15
+   |
 LL | const X: () = f(1);
-   |               ---- inside `X` at $DIR/recursive.rs:8:15
+   |               ^^^^
 
 error: aborting due to previous error; 1 warning emitted
 
diff --git a/src/test/ui/consts/uninhabited-const-issue-61744.stderr b/src/test/ui/consts/uninhabited-const-issue-61744.stderr
index 8b39f390bb4..3a94e19313f 100644
--- a/src/test/ui/consts/uninhabited-const-issue-61744.stderr
+++ b/src/test/ui/consts/uninhabited-const-issue-61744.stderr
@@ -2,143 +2,648 @@ error[E0080]: evaluation of `<i32 as Const>::CONSTANT` failed
   --> $DIR/uninhabited-const-issue-61744.rs:4:5
    |
 LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^ reached the configured maximum number of stack frames
+   |
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
    |     ^^^^^^^^^^^^^^^^^^
-   |     |
-   |     reached the configured maximum number of stack frames
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<!>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-   |     inside `fake_type::<i32>` at $DIR/uninhabited-const-issue-61744.rs:4:5
-...
-LL |     fake_type()
-   |     -----------
-   |     |
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-   |     inside `hint_unreachable` at $DIR/uninhabited-const-issue-61744.rs:8:5
-...
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<!>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `hint_unreachable`
+  --> $DIR/uninhabited-const-issue-61744.rs:8:5
+   |
+LL |     fake_type()
+   |     ^^^^^^^^^^^
+note: inside `fake_type::<i32>`
+  --> $DIR/uninhabited-const-issue-61744.rs:4:5
+   |
+LL |     hint_unreachable()
+   |     ^^^^^^^^^^^^^^^^^^
+note: inside `<i32 as Const>::CONSTANT`
+  --> $DIR/uninhabited-const-issue-61744.rs:12:36
+   |
 LL |     const CONSTANT: i32 = unsafe { fake_type() };
-   |                                    ----------- inside `<i32 as Const>::CONSTANT` at $DIR/uninhabited-const-issue-61744.rs:12:36
+   |                                    ^^^^^^^^^^^
 
 note: erroneous constant used
   --> $DIR/uninhabited-const-issue-61744.rs:18:10
diff --git a/src/test/ui/debuginfo/issue-105386-debuginfo-ub.rs b/src/test/ui/debuginfo/issue-105386-debuginfo-ub.rs
new file mode 100644
index 00000000000..6c6eb5d4e86
--- /dev/null
+++ b/src/test/ui/debuginfo/issue-105386-debuginfo-ub.rs
@@ -0,0 +1,20 @@
+// run-pass
+// compile-flags: --edition 2021 -Copt-level=3 -Cdebuginfo=2 -Zmir-opt-level=3
+
+fn main() {
+    TranslatorI.visit_pre();
+}
+
+impl TranslatorI {
+    fn visit_pre(self) {
+        Some(())
+            .map(|_| self.flags())
+            .unwrap_or_else(|| self.flags());
+    }
+}
+
+struct TranslatorI;
+
+impl TranslatorI {
+    fn flags(&self) {}
+}
diff --git a/src/test/ui/diagnostic-width/long-E0308.rs b/src/test/ui/diagnostic-width/long-E0308.rs
new file mode 100644
index 00000000000..3fd7a7110fd
--- /dev/null
+++ b/src/test/ui/diagnostic-width/long-E0308.rs
@@ -0,0 +1,86 @@
+// compile-flags: --diagnostic-width=60
+// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
+
+struct Atype<T, K>(T, K);
+struct Btype<T, K>(T, K);
+struct Ctype<T, K>(T, K);
+
+fn main() {
+    let x: Atype<
+      Btype<
+        Ctype<
+          Atype<
+            Btype<
+              Ctype<
+                Atype<
+                  Btype<
+                    Ctype<i32, i32>,
+                    i32
+                  >,
+                  i32
+                >,
+                i32
+              >,
+              i32
+            >,
+            i32
+          >,
+          i32
+        >,
+        i32
+      >,
+      i32
+    > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+        Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+            Ok("")
+        ))))))))))))))))))))))))))))))
+    ))))))))))))))))))))))))))))));
+    //~^^^^^ ERROR E0308
+
+    let _ = Some(Ok(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(
+        Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(
+            Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(Some(
+                Some(Some(Some(Some(Some(Some(Some(Some(Some("")))))))))
+            )))))))))))))))))
+        ))))))))))))))))))
+    ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+        Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+            Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
+        ))))))))))))))))))))))))))))))
+    ))))))))))))))))))))))));
+    //~^^^^^ ERROR E0308
+
+    let x: Atype<
+      Btype<
+        Ctype<
+          Atype<
+            Btype<
+              Ctype<
+                Atype<
+                  Btype<
+                    Ctype<i32, i32>,
+                    i32
+                  >,
+                  i32
+                >,
+                i32
+              >,
+              i32
+            >,
+            i32
+          >,
+          i32
+        >,
+        i32
+      >,
+      i32
+    > = ();
+    //~^ ERROR E0308
+
+    let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+        Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(
+            Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
+        ))))))))))))))))))))))))))))))
+    ))))))))))))))))))))))));
+    //~^^^^^ ERROR E0308
+}
diff --git a/src/test/ui/diagnostic-width/long-E0308.stderr b/src/test/ui/diagnostic-width/long-E0308.stderr
new file mode 100644
index 00000000000..487ab23a1c1
--- /dev/null
+++ b/src/test/ui/diagnostic-width/long-E0308.stderr
@@ -0,0 +1,80 @@
+error[E0308]: mismatched types
+  --> $DIR/long-E0308.rs:33:9
+   |
+LL |        let x: Atype<
+   |  _____________-
+LL | |        Btype<
+LL | |          Ctype<
+LL | |            Atype<
+...  |
+LL | |        i32
+LL | |      > = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok...
+   | | _____-___^
+   | ||_____|
+   |  |     expected due to this
+LL |  |         Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok...
+LL |  |             Ok("")
+LL |  |         ))))))))))))))))))))))))))))))
+LL |  |     ))))))))))))))))))))))))))))));
+   |  |__________________________________^ expected struct `Atype`, found enum `Result`
+   |
+   = note: expected struct `Atype<Btype<..., ...>, ...>`
+           the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+                found enum `Result<Result<..., ...>, ...>`
+           the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+
+error[E0308]: mismatched types
+  --> $DIR/long-E0308.rs:46:26
+   |
+LL |       ))))))))))))))))) == Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O...
+   |  __________________________^
+LL | |         Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(...
+LL | |             Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
+LL | |         ))))))))))))))))))))))))))))))
+LL | |     ))))))))))))))))))))))));
+   | |____________________________^ expected enum `Option`, found enum `Result`
+   |
+   = note: expected enum `Option<Result<..., ...>>`
+           the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+              found enum `Result<Result<..., ...>, ...>`
+           the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+
+error[E0308]: mismatched types
+  --> $DIR/long-E0308.rs:77:9
+   |
+LL |       let x: Atype<
+   |  ____________-
+LL | |       Btype<
+LL | |         Ctype<
+LL | |           Atype<
+...  |
+LL | |       i32
+LL | |     > = ();
+   | |     -   ^^ expected struct `Atype`, found `()`
+   | |_____|
+   |       expected due to this
+   |
+   = note: expected struct `Atype<Btype<..., ...>, ...>`
+           the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+           found unit type `()`
+
+error[E0308]: mismatched types
+  --> $DIR/long-E0308.rs:80:17
+   |
+LL |       let _: () = Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(O...
+   |  ____________--___^
+   | |            |
+   | |            expected due to this
+LL | |         Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(Ok(...
+LL | |             Ok(Ok(Ok(Ok(Ok(Ok(Ok("")))))))
+LL | |         ))))))))))))))))))))))))))))))
+LL | |     ))))))))))))))))))))))));
+   | |____________________________^ expected `()`, found enum `Result`
+   |
+   = note: expected unit type `()`
+                   found enum `Result<Result<..., ...>, ...>`
+           the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/long-E0308/long-E0308.long-type-hash.txt'
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/error-codes/E0275.stderr b/src/test/ui/error-codes/E0275.stderr
index 49a4d984af9..451a683ac8a 100644
--- a/src/test/ui/error-codes/E0275.stderr
+++ b/src/test/ui/error-codes/E0275.stderr
@@ -5,7 +5,7 @@ LL | impl<T> Foo for T where Bar<T>: Foo {}
    |                                 ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`E0275`)
-note: required for `Bar<Bar<Bar<Bar<Bar<Bar<...>>>>>>` to implement `Foo`
+note: required for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<...>>>>>>>>>>>>>>>>>>>>>` to implement `Foo`
   --> $DIR/E0275.rs:6:9
    |
 LL | impl<T> Foo for T where Bar<T>: Foo {}
diff --git a/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr b/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr
index c485bc5c3ab..760dcb615c8 100644
--- a/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr
+++ b/src/test/ui/feature-gates/feature-gate-impl_trait_in_fn_trait_return.stderr
@@ -3,12 +3,18 @@ error[E0562]: `impl Trait` only allowed in function and inherent method return t
    |
 LL | fn f() -> impl Fn() -> impl Sized { || () }
    |                        ^^^^^^^^^^
+   |
+   = note: see issue #99697 <https://github.com/rust-lang/rust/issues/99697> for more information
+   = help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable
 
 error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `Fn` trait return
   --> $DIR/feature-gate-impl_trait_in_fn_trait_return.rs:3:32
    |
 LL | fn g() -> &'static dyn Fn() -> impl Sized { &|| () }
    |                                ^^^^^^^^^^
+   |
+   = note: see issue #99697 <https://github.com/rust-lang/rust/issues/99697> for more information
+   = help: add `#![feature(impl_trait_in_fn_trait_return)]` to the crate attributes to enable
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/inference/deref-suggestion.stderr b/src/test/ui/inference/deref-suggestion.stderr
index 034005697b4..3db67cdb537 100644
--- a/src/test/ui/inference/deref-suggestion.stderr
+++ b/src/test/ui/inference/deref-suggestion.stderr
@@ -87,7 +87,10 @@ error[E0308]: mismatched types
   --> $DIR/deref-suggestion.rs:37:5
    |
 LL |     assert_eq!(3i32, &3i32);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `&i32`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     expected `i32`, found `&i32`
+   |     expected because this is `i32`
    |
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/infinite/infinite-recursion-const-fn.stderr b/src/test/ui/infinite/infinite-recursion-const-fn.stderr
index 620c9e110ff..53b603a47b5 100644
--- a/src/test/ui/infinite/infinite-recursion-const-fn.stderr
+++ b/src/test/ui/infinite/infinite-recursion-const-fn.stderr
@@ -2,143 +2,648 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/infinite-recursion-const-fn.rs:4:5
    |
 LL |     b()
+   |     ^^^ reached the configured maximum number of stack frames
+   |
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
    |     ^^^
-   |     |
-   |     reached the configured maximum number of stack frames
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-   |     inside `a` at $DIR/infinite-recursion-const-fn.rs:4:5
-...
-LL |     a()
-   |     ---
-   |     |
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-   |     inside `b` at $DIR/infinite-recursion-const-fn.rs:7:5
-LL | }
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `b`
+  --> $DIR/infinite-recursion-const-fn.rs:7:5
+   |
+LL |     a()
+   |     ^^^
+note: inside `a`
+  --> $DIR/infinite-recursion-const-fn.rs:4:5
+   |
+LL |     b()
+   |     ^^^
+note: inside `ARR::{constant#0}`
+  --> $DIR/infinite-recursion-const-fn.rs:9:18
+   |
 LL | const ARR: [i32; a()] = [5; 6];
-   |                  --- inside `ARR::{constant#0}` at $DIR/infinite-recursion-const-fn.rs:9:18
+   |                  ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/invalid/invalid-no-sanitize.stderr b/src/test/ui/invalid/invalid-no-sanitize.stderr
index d328cafa00b..4600034952b 100644
--- a/src/test/ui/invalid/invalid-no-sanitize.stderr
+++ b/src/test/ui/invalid/invalid-no-sanitize.stderr
@@ -4,7 +4,7 @@ error: invalid argument for `no_sanitize`
 LL | #[no_sanitize(brontosaurus)]
    |               ^^^^^^^^^^^^
    |
-   = note: expected one of: `address`, `cfi`, `hwaddress`, `memory`, `memtag`, `shadow-call-stack`, or `thread`
+   = note: expected one of: `address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow-call-stack`, or `thread`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-20413.stderr b/src/test/ui/issues/issue-20413.stderr
index 91509ceace8..78df445972c 100644
--- a/src/test/ui/issues/issue-20413.stderr
+++ b/src/test/ui/issues/issue-20413.stderr
@@ -14,7 +14,7 @@ LL | impl<T> Foo for T where NoData<T>: Foo {
    |                                    ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
-note: required for `NoData<NoData<NoData<NoData<NoData<NoData<...>>>>>>` to implement `Foo`
+note: required for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<...>>>>>>>>>>>>>` to implement `Foo`
   --> $DIR/issue-20413.rs:9:9
    |
 LL | impl<T> Foo for T where NoData<T>: Foo {
@@ -30,13 +30,13 @@ LL | impl<T> Bar for T where EvenLessData<T>: Baz {
    |                                          ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
-note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>` to implement `Bar`
+note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>>` to implement `Bar`
   --> $DIR/issue-20413.rs:28:9
    |
 LL | impl<T> Bar for T where EvenLessData<T>: Baz {
    |         ^^^     ^
    = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
-note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>` to implement `Baz`
+note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>>` to implement `Baz`
   --> $DIR/issue-20413.rs:35:9
    |
 LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
@@ -52,13 +52,13 @@ LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
    |                                          ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
-note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>` to implement `Baz`
+note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>>` to implement `Baz`
   --> $DIR/issue-20413.rs:35:9
    |
 LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
    |         ^^^     ^
    = note: the full type name has been written to '$TEST_BUILD_DIR/issues/issue-20413/issue-20413.long-type-hash.txt'
-note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<...>>>>>>` to implement `Bar`
+note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<...>>>>>>>` to implement `Bar`
   --> $DIR/issue-20413.rs:28:9
    |
 LL | impl<T> Bar for T where EvenLessData<T>: Baz {
diff --git a/src/test/ui/issues/issue-23122-2.stderr b/src/test/ui/issues/issue-23122-2.stderr
index 5828e027b59..1f50b06a0e4 100644
--- a/src/test/ui/issues/issue-23122-2.stderr
+++ b/src/test/ui/issues/issue-23122-2.stderr
@@ -5,7 +5,7 @@ LL |     type Next = <GetNext<T::Next> as Next>::Next;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_23122_2`)
-note: required for `GetNext<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next`
+note: required for `GetNext<<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next`
   --> $DIR/issue-23122-2.rs:10:15
    |
 LL | impl<T: Next> Next for GetNext<T> {
diff --git a/src/test/ui/issues/issue-47486.stderr b/src/test/ui/issues/issue-47486.stderr
index 2bd24f08c1e..c7e9af70e64 100644
--- a/src/test/ui/issues/issue-47486.stderr
+++ b/src/test/ui/issues/issue-47486.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/issue-47486.rs:2:10
    |
 LL |     () < std::mem::size_of::<_>();
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `usize`
+   |     --   ^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `usize`
+   |     |
+   |     expected because this is `()`
 
 error[E0282]: type annotations needed
   --> $DIR/issue-47486.rs:3:11
diff --git a/src/test/ui/limits/issue-55878.stderr b/src/test/ui/limits/issue-55878.stderr
index e35f9f14c7e..f17f8141b90 100644
--- a/src/test/ui/limits/issue-55878.stderr
+++ b/src/test/ui/limits/issue-55878.stderr
@@ -2,12 +2,18 @@ error[E0080]: values of the type `[u8; SIZE]` are too big for the current archit
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
    |
 LL |     intrinsics::size_of::<T>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ inside `std::mem::size_of::<[u8; SIZE]>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-  ::: $DIR/issue-55878.rs:7:26
+note: inside `std::mem::size_of::<[u8; SIZE]>`
+  --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
+   |
+LL |     intrinsics::size_of::<T>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+note: inside `main`
+  --> $DIR/issue-55878.rs:7:26
    |
 LL |     println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>());
-   |                          ---------------------------------------------- inside `main` at $DIR/issue-55878.rs:7:26
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 note: erroneous constant used
   --> $DIR/issue-55878.rs:7:26
diff --git a/src/test/ui/lint/lint-missing-copy-implementations-allow.rs b/src/test/ui/lint/lint-missing-copy-implementations-allow.rs
new file mode 100644
index 00000000000..051a905aed6
--- /dev/null
+++ b/src/test/ui/lint/lint-missing-copy-implementations-allow.rs
@@ -0,0 +1,35 @@
+// check-pass
+#![deny(missing_copy_implementations)]
+
+// Don't recommend implementing Copy on something stateful like an iterator.
+pub struct MyIterator {
+    num: u8,
+}
+
+impl Iterator for MyIterator {
+    type Item = u8;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        todo!()
+    }
+}
+
+pub struct Handle {
+    inner: *mut (),
+}
+
+pub struct Handle2 {
+    inner: *const (),
+}
+
+pub enum MaybeHandle {
+    Ptr(*mut ()),
+}
+
+pub union UnionHandle {
+    ptr: *mut (),
+}
+
+pub struct Array([u8; 2048]);
+
+fn main() {}
diff --git a/src/test/ui/lint/unused/issue-54538-unused-parens-lint.fixed b/src/test/ui/lint/unused/issue-54538-unused-parens-lint.fixed
index 0b3fe9371f7..71ebaea8ed2 100644
--- a/src/test/ui/lint/unused/issue-54538-unused-parens-lint.fixed
+++ b/src/test/ui/lint/unused/issue-54538-unused-parens-lint.fixed
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![feature(box_patterns, stmt_expr_attributes)]
+#![feature(box_patterns, stmt_expr_attributes, yeet_expr)]
 
 #![allow(
     dead_code,
@@ -25,6 +25,13 @@ fn _no_lint_attr() {
     let _x = #[allow(dead_code)] (1 + 2);
 }
 
+fn _no_lint_yeet() -> Result<(), ()> {
+    #[allow(unreachable_code)]
+    if (do yeet) {}
+
+    Ok(())
+}
+
 // Don't lint in these cases (#64106).
 fn or_patterns_no_lint() {
     match Box::new(0) {
diff --git a/src/test/ui/lint/unused/issue-54538-unused-parens-lint.rs b/src/test/ui/lint/unused/issue-54538-unused-parens-lint.rs
index 1e78ec5f7d9..28b662dd024 100644
--- a/src/test/ui/lint/unused/issue-54538-unused-parens-lint.rs
+++ b/src/test/ui/lint/unused/issue-54538-unused-parens-lint.rs
@@ -1,6 +1,6 @@
 // run-rustfix
 
-#![feature(box_patterns, stmt_expr_attributes)]
+#![feature(box_patterns, stmt_expr_attributes, yeet_expr)]
 
 #![allow(
     dead_code,
@@ -25,6 +25,13 @@ fn _no_lint_attr() {
     let _x = #[allow(dead_code)] (1 + 2);
 }
 
+fn _no_lint_yeet() -> Result<(), ()> {
+    #[allow(unreachable_code)]
+    if (do yeet) {}
+
+    Ok(())
+}
+
 // Don't lint in these cases (#64106).
 fn or_patterns_no_lint() {
     match Box::new(0) {
diff --git a/src/test/ui/lint/unused/issue-54538-unused-parens-lint.stderr b/src/test/ui/lint/unused/issue-54538-unused-parens-lint.stderr
index c73884663c8..a5e69e6d938 100644
--- a/src/test/ui/lint/unused/issue-54538-unused-parens-lint.stderr
+++ b/src/test/ui/lint/unused/issue-54538-unused-parens-lint.stderr
@@ -76,7 +76,7 @@ LL +     let _ = |a: u8| 0;
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:49:12
+  --> $DIR/issue-54538-unused-parens-lint.rs:56:12
    |
 LL |     if let (0 | 1) = 0 {}
    |            ^     ^
@@ -88,7 +88,7 @@ LL +     if let 0 | 1 = 0 {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:50:13
+  --> $DIR/issue-54538-unused-parens-lint.rs:57:13
    |
 LL |     if let ((0 | 1),) = (0,) {}
    |             ^     ^
@@ -100,7 +100,7 @@ LL +     if let (0 | 1,) = (0,) {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:51:13
+  --> $DIR/issue-54538-unused-parens-lint.rs:58:13
    |
 LL |     if let [(0 | 1)] = [0] {}
    |             ^     ^
@@ -112,7 +112,7 @@ LL +     if let [0 | 1] = [0] {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:52:16
+  --> $DIR/issue-54538-unused-parens-lint.rs:59:16
    |
 LL |     if let 0 | (1 | 2) = 0 {}
    |                ^     ^
@@ -124,7 +124,7 @@ LL +     if let 0 | 1 | 2 = 0 {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:54:15
+  --> $DIR/issue-54538-unused-parens-lint.rs:61:15
    |
 LL |     if let TS((0 | 1)) = TS(0) {}
    |               ^     ^
@@ -136,7 +136,7 @@ LL +     if let TS(0 | 1) = TS(0) {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:56:20
+  --> $DIR/issue-54538-unused-parens-lint.rs:63:20
    |
 LL |     if let NS { f: (0 | 1) } = (NS { f: 0 }) {}
    |                    ^     ^
@@ -148,7 +148,7 @@ LL +     if let NS { f: 0 | 1 } = (NS { f: 0 }) {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:66:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:73:9
    |
 LL |         (_) => {}
    |         ^ ^
@@ -160,7 +160,7 @@ LL +         _ => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:67:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:74:9
    |
 LL |         (y) => {}
    |         ^ ^
@@ -172,7 +172,7 @@ LL +         y => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:68:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:75:9
    |
 LL |         (ref r) => {}
    |         ^     ^
@@ -184,7 +184,7 @@ LL +         ref r => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:69:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:76:9
    |
 LL |         (e @ 1...2) => {}
    |         ^         ^
@@ -196,7 +196,7 @@ LL +         e @ 1...2 => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:75:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:82:9
    |
 LL |         (e @ &(1...2)) => {}
    |         ^            ^
@@ -208,7 +208,7 @@ LL +         e @ &(1...2) => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:76:10
+  --> $DIR/issue-54538-unused-parens-lint.rs:83:10
    |
 LL |         &(_) => {}
    |          ^ ^
@@ -220,7 +220,7 @@ LL +         &_ => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:87:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:94:9
    |
 LL |         (_) => {}
    |         ^ ^
@@ -232,7 +232,7 @@ LL +         _ => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:88:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:95:9
    |
 LL |         (y) => {}
    |         ^ ^
@@ -244,7 +244,7 @@ LL +         y => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:89:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:96:9
    |
 LL |         (ref r) => {}
    |         ^     ^
@@ -256,7 +256,7 @@ LL +         ref r => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:90:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:97:9
    |
 LL |         (e @ 1..=2) => {}
    |         ^         ^
@@ -268,7 +268,7 @@ LL +         e @ 1..=2 => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:96:9
+  --> $DIR/issue-54538-unused-parens-lint.rs:103:9
    |
 LL |         (e @ &(1..=2)) => {}
    |         ^            ^
@@ -280,7 +280,7 @@ LL +         e @ &(1..=2) => {}
    |
 
 error: unnecessary parentheses around pattern
-  --> $DIR/issue-54538-unused-parens-lint.rs:97:10
+  --> $DIR/issue-54538-unused-parens-lint.rs:104:10
    |
 LL |         &(_) => {}
    |          ^ ^
diff --git a/src/test/ui/macros/macro-in-expression-context.stderr b/src/test/ui/macros/macro-in-expression-context.stderr
index 1023189eaa3..36aba8aa08a 100644
--- a/src/test/ui/macros/macro-in-expression-context.stderr
+++ b/src/test/ui/macros/macro-in-expression-context.stderr
@@ -5,11 +5,13 @@ LL |         assert_eq!("B", "B");
    |         ^^^^^^^^^
 ...
 LL |     foo!()
-   |     ------- help: you might be missing a semicolon here: `;`
-   |     |
-   |     caused by the macro expansion here
+   |     ------ caused by the macro expansion here
    |
    = note: the usage of `foo!` is likely invalid in expression context
+help: you might be missing a semicolon here
+   |
+LL |     foo!();
+   |           +
 
 warning: trailing semicolon in macro used in expression position
   --> $DIR/macro-in-expression-context.rs:5:29
diff --git a/src/test/ui/mir/issue-95978-validator-lifetime-comparison.rs b/src/test/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs
index cd6c5bf2719..cd6c5bf2719 100644
--- a/src/test/ui/mir/issue-95978-validator-lifetime-comparison.rs
+++ b/src/test/ui/mir/validate/issue-95978-validator-lifetime-comparison.rs
diff --git a/src/test/ui/mir/validate/needs-reveal-all.rs b/src/test/ui/mir/validate/needs-reveal-all.rs
new file mode 100644
index 00000000000..3852daf245e
--- /dev/null
+++ b/src/test/ui/mir/validate/needs-reveal-all.rs
@@ -0,0 +1,52 @@
+// Regression test for #105009. the issue here was that even after the `RevealAll` pass,
+// `validate` still used `Reveal::UserFacing`. This meant that it now ends up comparing
+// opaque types with their revealed version, resulting in an ICE.
+//
+// We're using these flags to run the `RevealAll` pass while making it less likely to
+// accidentally removing the assignment from `Foo<fn_ptr>` to `Foo<fn_def>`.
+
+// compile-flags: -Zinline_mir=yes -Zmir-opt-level=0 -Zvalidate-mir
+// run-pass
+
+use std::hint::black_box;
+
+trait Func {
+    type Ret: Id;
+}
+
+trait Id {
+    type Assoc;
+}
+impl Id for u32 {
+    type Assoc = u32;
+}
+impl Id for i32 {
+    type Assoc = i32;
+}
+
+impl<F: FnOnce() -> R, R: Id> Func for F {
+    type Ret = R;
+}
+
+fn bar() -> impl Copy + Id {
+    0u32
+}
+
+struct Foo<T: Func> {
+    _func: T,
+    value: Option<<<T as Func>::Ret as Id>::Assoc>,
+}
+
+fn main() {
+    let mut fn_def = black_box(Foo {
+        _func: bar,
+        value: None,
+    });
+    let fn_ptr = black_box(Foo {
+        _func: bar as fn() -> _,
+        value: None,
+    });
+
+    fn_def.value = fn_ptr.value;
+    black_box(fn_def);
+}
diff --git a/src/test/ui/numeric/numeric-cast-binop.stderr b/src/test/ui/numeric/numeric-cast-binop.stderr
index 2f58f164985..d5213e3f5b6 100644
--- a/src/test/ui/numeric/numeric-cast-binop.stderr
+++ b/src/test/ui/numeric/numeric-cast-binop.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:23:16
    |
 LL |         x_u8 > x_u16;
-   |                ^^^^^ expected `u8`, found `u16`
+   |         ----   ^^^^^ expected `u8`, found `u16`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `u16`, matching the type of `x_u16`
    |
@@ -13,7 +15,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:25:16
    |
 LL |         x_u8 > x_u32;
-   |                ^^^^^ expected `u8`, found `u32`
+   |         ----   ^^^^^ expected `u8`, found `u32`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `u32`, matching the type of `x_u32`
    |
@@ -24,7 +28,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:27:16
    |
 LL |         x_u8 > x_u64;
-   |                ^^^^^ expected `u8`, found `u64`
+   |         ----   ^^^^^ expected `u8`, found `u64`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `u64`, matching the type of `x_u64`
    |
@@ -35,7 +41,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:29:16
    |
 LL |         x_u8 > x_u128;
-   |                ^^^^^^ expected `u8`, found `u128`
+   |         ----   ^^^^^^ expected `u8`, found `u128`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `u128`, matching the type of `x_u128`
    |
@@ -46,7 +54,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:31:16
    |
 LL |         x_u8 > x_usize;
-   |                ^^^^^^^ expected `u8`, found `usize`
+   |         ----   ^^^^^^^ expected `u8`, found `usize`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `usize`, matching the type of `x_usize`
    |
@@ -57,7 +67,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:34:17
    |
 LL |         x_u16 > x_u8;
-   |                 ^^^^ expected `u16`, found `u8`
+   |         -----   ^^^^ expected `u16`, found `u8`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert a `u8` to a `u16`
    |
@@ -68,7 +80,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:36:17
    |
 LL |         x_u16 > x_u32;
-   |                 ^^^^^ expected `u16`, found `u32`
+   |         -----   ^^^^^ expected `u16`, found `u32`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert `x_u16` from `u16` to `u32`, matching the type of `x_u32`
    |
@@ -79,7 +93,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:38:17
    |
 LL |         x_u16 > x_u64;
-   |                 ^^^^^ expected `u16`, found `u64`
+   |         -----   ^^^^^ expected `u16`, found `u64`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert `x_u16` from `u16` to `u64`, matching the type of `x_u64`
    |
@@ -90,7 +106,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:40:17
    |
 LL |         x_u16 > x_u128;
-   |                 ^^^^^^ expected `u16`, found `u128`
+   |         -----   ^^^^^^ expected `u16`, found `u128`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert `x_u16` from `u16` to `u128`, matching the type of `x_u128`
    |
@@ -101,7 +119,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:42:17
    |
 LL |         x_u16 > x_usize;
-   |                 ^^^^^^^ expected `u16`, found `usize`
+   |         -----   ^^^^^^^ expected `u16`, found `usize`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert `x_u16` from `u16` to `usize`, matching the type of `x_usize`
    |
@@ -112,7 +132,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:45:17
    |
 LL |         x_u32 > x_u8;
-   |                 ^^^^ expected `u32`, found `u8`
+   |         -----   ^^^^ expected `u32`, found `u8`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert a `u8` to a `u32`
    |
@@ -123,7 +145,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:47:17
    |
 LL |         x_u32 > x_u16;
-   |                 ^^^^^ expected `u32`, found `u16`
+   |         -----   ^^^^^ expected `u32`, found `u16`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert a `u16` to a `u32`
    |
@@ -134,7 +158,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:49:17
    |
 LL |         x_u32 > x_u64;
-   |                 ^^^^^ expected `u32`, found `u64`
+   |         -----   ^^^^^ expected `u32`, found `u64`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert `x_u32` from `u32` to `u64`, matching the type of `x_u64`
    |
@@ -145,7 +171,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:51:17
    |
 LL |         x_u32 > x_u128;
-   |                 ^^^^^^ expected `u32`, found `u128`
+   |         -----   ^^^^^^ expected `u32`, found `u128`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert `x_u32` from `u32` to `u128`, matching the type of `x_u128`
    |
@@ -156,7 +184,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:53:17
    |
 LL |         x_u32 > x_usize;
-   |                 ^^^^^^^ expected `u32`, found `usize`
+   |         -----   ^^^^^^^ expected `u32`, found `usize`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert a `usize` to a `u32` and panic if the converted value doesn't fit
    |
@@ -167,7 +197,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:56:17
    |
 LL |         x_u64 > x_u8;
-   |                 ^^^^ expected `u64`, found `u8`
+   |         -----   ^^^^ expected `u64`, found `u8`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert a `u8` to a `u64`
    |
@@ -178,7 +210,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:58:17
    |
 LL |         x_u64 > x_u16;
-   |                 ^^^^^ expected `u64`, found `u16`
+   |         -----   ^^^^^ expected `u64`, found `u16`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert a `u16` to a `u64`
    |
@@ -189,7 +223,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:60:17
    |
 LL |         x_u64 > x_u32;
-   |                 ^^^^^ expected `u64`, found `u32`
+   |         -----   ^^^^^ expected `u64`, found `u32`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert a `u32` to a `u64`
    |
@@ -200,7 +236,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:62:17
    |
 LL |         x_u64 > x_u128;
-   |                 ^^^^^^ expected `u64`, found `u128`
+   |         -----   ^^^^^^ expected `u64`, found `u128`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert `x_u64` from `u64` to `u128`, matching the type of `x_u128`
    |
@@ -211,7 +249,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:64:17
    |
 LL |         x_u64 > x_usize;
-   |                 ^^^^^^^ expected `u64`, found `usize`
+   |         -----   ^^^^^^^ expected `u64`, found `usize`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit
    |
@@ -222,7 +262,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:67:18
    |
 LL |         x_u128 > x_u8;
-   |                  ^^^^ expected `u128`, found `u8`
+   |         ------   ^^^^ expected `u128`, found `u8`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert a `u8` to a `u128`
    |
@@ -233,7 +275,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:69:18
    |
 LL |         x_u128 > x_u16;
-   |                  ^^^^^ expected `u128`, found `u16`
+   |         ------   ^^^^^ expected `u128`, found `u16`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert a `u16` to a `u128`
    |
@@ -244,7 +288,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:71:18
    |
 LL |         x_u128 > x_u32;
-   |                  ^^^^^ expected `u128`, found `u32`
+   |         ------   ^^^^^ expected `u128`, found `u32`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert a `u32` to a `u128`
    |
@@ -255,7 +301,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:73:18
    |
 LL |         x_u128 > x_u64;
-   |                  ^^^^^ expected `u128`, found `u64`
+   |         ------   ^^^^^ expected `u128`, found `u64`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert a `u64` to a `u128`
    |
@@ -266,7 +314,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:75:18
    |
 LL |         x_u128 > x_usize;
-   |                  ^^^^^^^ expected `u128`, found `usize`
+   |         ------   ^^^^^^^ expected `u128`, found `usize`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert a `usize` to a `u128` and panic if the converted value doesn't fit
    |
@@ -277,7 +327,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:78:19
    |
 LL |         x_usize > x_u8;
-   |                   ^^^^ expected `usize`, found `u8`
+   |         -------   ^^^^ expected `usize`, found `u8`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert a `u8` to a `usize`
    |
@@ -288,7 +340,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:80:19
    |
 LL |         x_usize > x_u16;
-   |                   ^^^^^ expected `usize`, found `u16`
+   |         -------   ^^^^^ expected `usize`, found `u16`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert a `u16` to a `usize`
    |
@@ -299,7 +353,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:82:19
    |
 LL |         x_usize > x_u32;
-   |                   ^^^^^ expected `usize`, found `u32`
+   |         -------   ^^^^^ expected `usize`, found `u32`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert a `u32` to a `usize` and panic if the converted value doesn't fit
    |
@@ -310,7 +366,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:84:19
    |
 LL |         x_usize > x_u64;
-   |                   ^^^^^ expected `usize`, found `u64`
+   |         -------   ^^^^^ expected `usize`, found `u64`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert a `u64` to a `usize` and panic if the converted value doesn't fit
    |
@@ -321,7 +379,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:86:19
    |
 LL |         x_usize > x_u128;
-   |                   ^^^^^^ expected `usize`, found `u128`
+   |         -------   ^^^^^^ expected `usize`, found `u128`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert a `u128` to a `usize` and panic if the converted value doesn't fit
    |
@@ -332,7 +392,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:92:16
    |
 LL |         x_i8 > x_i16;
-   |                ^^^^^ expected `i8`, found `i16`
+   |         ----   ^^^^^ expected `i8`, found `i16`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert `x_i8` from `i8` to `i16`, matching the type of `x_i16`
    |
@@ -343,7 +405,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:94:16
    |
 LL |         x_i8 > x_i32;
-   |                ^^^^^ expected `i8`, found `i32`
+   |         ----   ^^^^^ expected `i8`, found `i32`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert `x_i8` from `i8` to `i32`, matching the type of `x_i32`
    |
@@ -354,7 +418,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:96:16
    |
 LL |         x_i8 > x_i64;
-   |                ^^^^^ expected `i8`, found `i64`
+   |         ----   ^^^^^ expected `i8`, found `i64`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert `x_i8` from `i8` to `i64`, matching the type of `x_i64`
    |
@@ -365,7 +431,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:98:16
    |
 LL |         x_i8 > x_i128;
-   |                ^^^^^^ expected `i8`, found `i128`
+   |         ----   ^^^^^^ expected `i8`, found `i128`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert `x_i8` from `i8` to `i128`, matching the type of `x_i128`
    |
@@ -376,7 +444,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:100:16
    |
 LL |         x_i8 > x_isize;
-   |                ^^^^^^^ expected `i8`, found `isize`
+   |         ----   ^^^^^^^ expected `i8`, found `isize`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert `x_i8` from `i8` to `isize`, matching the type of `x_isize`
    |
@@ -387,7 +457,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:103:17
    |
 LL |         x_i16 > x_i8;
-   |                 ^^^^ expected `i16`, found `i8`
+   |         -----   ^^^^ expected `i16`, found `i8`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert an `i8` to an `i16`
    |
@@ -398,7 +470,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:105:17
    |
 LL |         x_i16 > x_i32;
-   |                 ^^^^^ expected `i16`, found `i32`
+   |         -----   ^^^^^ expected `i16`, found `i32`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert `x_i16` from `i16` to `i32`, matching the type of `x_i32`
    |
@@ -409,7 +483,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:107:17
    |
 LL |         x_i16 > x_i64;
-   |                 ^^^^^ expected `i16`, found `i64`
+   |         -----   ^^^^^ expected `i16`, found `i64`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert `x_i16` from `i16` to `i64`, matching the type of `x_i64`
    |
@@ -420,7 +496,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:109:17
    |
 LL |         x_i16 > x_i128;
-   |                 ^^^^^^ expected `i16`, found `i128`
+   |         -----   ^^^^^^ expected `i16`, found `i128`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert `x_i16` from `i16` to `i128`, matching the type of `x_i128`
    |
@@ -431,7 +509,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:111:17
    |
 LL |         x_i16 > x_isize;
-   |                 ^^^^^^^ expected `i16`, found `isize`
+   |         -----   ^^^^^^^ expected `i16`, found `isize`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert `x_i16` from `i16` to `isize`, matching the type of `x_isize`
    |
@@ -442,7 +522,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:114:17
    |
 LL |         x_i32 > x_i8;
-   |                 ^^^^ expected `i32`, found `i8`
+   |         -----   ^^^^ expected `i32`, found `i8`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert an `i8` to an `i32`
    |
@@ -453,7 +535,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:116:17
    |
 LL |         x_i32 > x_i16;
-   |                 ^^^^^ expected `i32`, found `i16`
+   |         -----   ^^^^^ expected `i32`, found `i16`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert an `i16` to an `i32`
    |
@@ -464,7 +548,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:118:17
    |
 LL |         x_i32 > x_i64;
-   |                 ^^^^^ expected `i32`, found `i64`
+   |         -----   ^^^^^ expected `i32`, found `i64`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert `x_i32` from `i32` to `i64`, matching the type of `x_i64`
    |
@@ -475,7 +561,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:120:17
    |
 LL |         x_i32 > x_i128;
-   |                 ^^^^^^ expected `i32`, found `i128`
+   |         -----   ^^^^^^ expected `i32`, found `i128`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert `x_i32` from `i32` to `i128`, matching the type of `x_i128`
    |
@@ -486,7 +574,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:122:17
    |
 LL |         x_i32 > x_isize;
-   |                 ^^^^^^^ expected `i32`, found `isize`
+   |         -----   ^^^^^^^ expected `i32`, found `isize`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert an `isize` to an `i32` and panic if the converted value doesn't fit
    |
@@ -497,7 +587,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:125:17
    |
 LL |         x_i64 > x_i8;
-   |                 ^^^^ expected `i64`, found `i8`
+   |         -----   ^^^^ expected `i64`, found `i8`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert an `i8` to an `i64`
    |
@@ -508,7 +600,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:127:17
    |
 LL |         x_i64 > x_i16;
-   |                 ^^^^^ expected `i64`, found `i16`
+   |         -----   ^^^^^ expected `i64`, found `i16`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert an `i16` to an `i64`
    |
@@ -519,7 +613,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:129:17
    |
 LL |         x_i64 > x_i32;
-   |                 ^^^^^ expected `i64`, found `i32`
+   |         -----   ^^^^^ expected `i64`, found `i32`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert an `i32` to an `i64`
    |
@@ -530,7 +626,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:131:17
    |
 LL |         x_i64 > x_i128;
-   |                 ^^^^^^ expected `i64`, found `i128`
+   |         -----   ^^^^^^ expected `i64`, found `i128`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert `x_i64` from `i64` to `i128`, matching the type of `x_i128`
    |
@@ -541,7 +639,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:133:17
    |
 LL |         x_i64 > x_isize;
-   |                 ^^^^^^^ expected `i64`, found `isize`
+   |         -----   ^^^^^^^ expected `i64`, found `isize`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert an `isize` to an `i64` and panic if the converted value doesn't fit
    |
@@ -552,7 +652,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:136:18
    |
 LL |         x_i128 > x_i8;
-   |                  ^^^^ expected `i128`, found `i8`
+   |         ------   ^^^^ expected `i128`, found `i8`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert an `i8` to an `i128`
    |
@@ -563,7 +665,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:138:18
    |
 LL |         x_i128 > x_i16;
-   |                  ^^^^^ expected `i128`, found `i16`
+   |         ------   ^^^^^ expected `i128`, found `i16`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert an `i16` to an `i128`
    |
@@ -574,7 +678,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:140:18
    |
 LL |         x_i128 > x_i32;
-   |                  ^^^^^ expected `i128`, found `i32`
+   |         ------   ^^^^^ expected `i128`, found `i32`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert an `i32` to an `i128`
    |
@@ -585,7 +691,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:142:18
    |
 LL |         x_i128 > x_i64;
-   |                  ^^^^^ expected `i128`, found `i64`
+   |         ------   ^^^^^ expected `i128`, found `i64`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert an `i64` to an `i128`
    |
@@ -596,7 +704,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:144:18
    |
 LL |         x_i128 > x_isize;
-   |                  ^^^^^^^ expected `i128`, found `isize`
+   |         ------   ^^^^^^^ expected `i128`, found `isize`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert an `isize` to an `i128` and panic if the converted value doesn't fit
    |
@@ -607,7 +717,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:147:19
    |
 LL |         x_isize > x_i8;
-   |                   ^^^^ expected `isize`, found `i8`
+   |         -------   ^^^^ expected `isize`, found `i8`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert an `i8` to an `isize`
    |
@@ -618,7 +730,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:149:19
    |
 LL |         x_isize > x_i16;
-   |                   ^^^^^ expected `isize`, found `i16`
+   |         -------   ^^^^^ expected `isize`, found `i16`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert an `i16` to an `isize`
    |
@@ -629,7 +743,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:151:19
    |
 LL |         x_isize > x_i32;
-   |                   ^^^^^ expected `isize`, found `i32`
+   |         -------   ^^^^^ expected `isize`, found `i32`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert an `i32` to an `isize` and panic if the converted value doesn't fit
    |
@@ -640,7 +756,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:153:19
    |
 LL |         x_isize > x_i64;
-   |                   ^^^^^ expected `isize`, found `i64`
+   |         -------   ^^^^^ expected `isize`, found `i64`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert an `i64` to an `isize` and panic if the converted value doesn't fit
    |
@@ -651,7 +769,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:155:19
    |
 LL |         x_isize > x_i128;
-   |                   ^^^^^^ expected `isize`, found `i128`
+   |         -------   ^^^^^^ expected `isize`, found `i128`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert an `i128` to an `isize` and panic if the converted value doesn't fit
    |
@@ -662,7 +782,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:161:16
    |
 LL |         x_u8 > x_i8;
-   |                ^^^^ expected `u8`, found `i8`
+   |         ----   ^^^^ expected `u8`, found `i8`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert an `i8` to a `u8` and panic if the converted value doesn't fit
    |
@@ -673,7 +795,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:163:16
    |
 LL |         x_u8 > x_i16;
-   |                ^^^^^ expected `u8`, found `i16`
+   |         ----   ^^^^^ expected `u8`, found `i16`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `i16`, matching the type of `x_i16`
    |
@@ -684,7 +808,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:165:16
    |
 LL |         x_u8 > x_i32;
-   |                ^^^^^ expected `u8`, found `i32`
+   |         ----   ^^^^^ expected `u8`, found `i32`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `i32`, matching the type of `x_i32`
    |
@@ -695,7 +821,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:167:16
    |
 LL |         x_u8 > x_i64;
-   |                ^^^^^ expected `u8`, found `i64`
+   |         ----   ^^^^^ expected `u8`, found `i64`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `i64`, matching the type of `x_i64`
    |
@@ -706,7 +834,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:169:16
    |
 LL |         x_u8 > x_i128;
-   |                ^^^^^^ expected `u8`, found `i128`
+   |         ----   ^^^^^^ expected `u8`, found `i128`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `i128`, matching the type of `x_i128`
    |
@@ -717,7 +847,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:171:16
    |
 LL |         x_u8 > x_isize;
-   |                ^^^^^^^ expected `u8`, found `isize`
+   |         ----   ^^^^^^^ expected `u8`, found `isize`
+   |         |
+   |         expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `isize`, matching the type of `x_isize`
    |
@@ -728,7 +860,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:174:17
    |
 LL |         x_u16 > x_i8;
-   |                 ^^^^ expected `u16`, found `i8`
+   |         -----   ^^^^ expected `u16`, found `i8`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert an `i8` to a `u16` and panic if the converted value doesn't fit
    |
@@ -739,7 +873,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:176:17
    |
 LL |         x_u16 > x_i16;
-   |                 ^^^^^ expected `u16`, found `i16`
+   |         -----   ^^^^^ expected `u16`, found `i16`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert an `i16` to a `u16` and panic if the converted value doesn't fit
    |
@@ -750,7 +886,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:178:17
    |
 LL |         x_u16 > x_i32;
-   |                 ^^^^^ expected `u16`, found `i32`
+   |         -----   ^^^^^ expected `u16`, found `i32`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert `x_u16` from `u16` to `i32`, matching the type of `x_i32`
    |
@@ -761,7 +899,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:180:17
    |
 LL |         x_u16 > x_i64;
-   |                 ^^^^^ expected `u16`, found `i64`
+   |         -----   ^^^^^ expected `u16`, found `i64`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert `x_u16` from `u16` to `i64`, matching the type of `x_i64`
    |
@@ -772,7 +912,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:182:17
    |
 LL |         x_u16 > x_i128;
-   |                 ^^^^^^ expected `u16`, found `i128`
+   |         -----   ^^^^^^ expected `u16`, found `i128`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert `x_u16` from `u16` to `i128`, matching the type of `x_i128`
    |
@@ -783,7 +925,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:184:17
    |
 LL |         x_u16 > x_isize;
-   |                 ^^^^^^^ expected `u16`, found `isize`
+   |         -----   ^^^^^^^ expected `u16`, found `isize`
+   |         |
+   |         expected because this is `u16`
    |
 help: you can convert an `isize` to a `u16` and panic if the converted value doesn't fit
    |
@@ -794,7 +938,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:187:17
    |
 LL |         x_u32 > x_i8;
-   |                 ^^^^ expected `u32`, found `i8`
+   |         -----   ^^^^ expected `u32`, found `i8`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert an `i8` to a `u32` and panic if the converted value doesn't fit
    |
@@ -805,7 +951,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:189:17
    |
 LL |         x_u32 > x_i16;
-   |                 ^^^^^ expected `u32`, found `i16`
+   |         -----   ^^^^^ expected `u32`, found `i16`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert an `i16` to a `u32` and panic if the converted value doesn't fit
    |
@@ -816,7 +964,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:191:17
    |
 LL |         x_u32 > x_i32;
-   |                 ^^^^^ expected `u32`, found `i32`
+   |         -----   ^^^^^ expected `u32`, found `i32`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
    |
@@ -827,7 +977,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:193:17
    |
 LL |         x_u32 > x_i64;
-   |                 ^^^^^ expected `u32`, found `i64`
+   |         -----   ^^^^^ expected `u32`, found `i64`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert `x_u32` from `u32` to `i64`, matching the type of `x_i64`
    |
@@ -838,7 +990,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:195:17
    |
 LL |         x_u32 > x_i128;
-   |                 ^^^^^^ expected `u32`, found `i128`
+   |         -----   ^^^^^^ expected `u32`, found `i128`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert `x_u32` from `u32` to `i128`, matching the type of `x_i128`
    |
@@ -849,7 +1003,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:197:17
    |
 LL |         x_u32 > x_isize;
-   |                 ^^^^^^^ expected `u32`, found `isize`
+   |         -----   ^^^^^^^ expected `u32`, found `isize`
+   |         |
+   |         expected because this is `u32`
    |
 help: you can convert an `isize` to a `u32` and panic if the converted value doesn't fit
    |
@@ -860,7 +1016,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:200:17
    |
 LL |         x_u64 > x_i8;
-   |                 ^^^^ expected `u64`, found `i8`
+   |         -----   ^^^^ expected `u64`, found `i8`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert an `i8` to a `u64` and panic if the converted value doesn't fit
    |
@@ -871,7 +1029,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:202:17
    |
 LL |         x_u64 > x_i16;
-   |                 ^^^^^ expected `u64`, found `i16`
+   |         -----   ^^^^^ expected `u64`, found `i16`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert an `i16` to a `u64` and panic if the converted value doesn't fit
    |
@@ -882,7 +1042,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:204:17
    |
 LL |         x_u64 > x_i32;
-   |                 ^^^^^ expected `u64`, found `i32`
+   |         -----   ^^^^^ expected `u64`, found `i32`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert an `i32` to a `u64` and panic if the converted value doesn't fit
    |
@@ -893,7 +1055,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:206:17
    |
 LL |         x_u64 > x_i64;
-   |                 ^^^^^ expected `u64`, found `i64`
+   |         -----   ^^^^^ expected `u64`, found `i64`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert an `i64` to a `u64` and panic if the converted value doesn't fit
    |
@@ -904,7 +1068,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:208:17
    |
 LL |         x_u64 > x_i128;
-   |                 ^^^^^^ expected `u64`, found `i128`
+   |         -----   ^^^^^^ expected `u64`, found `i128`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert `x_u64` from `u64` to `i128`, matching the type of `x_i128`
    |
@@ -915,7 +1081,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:210:17
    |
 LL |         x_u64 > x_isize;
-   |                 ^^^^^^^ expected `u64`, found `isize`
+   |         -----   ^^^^^^^ expected `u64`, found `isize`
+   |         |
+   |         expected because this is `u64`
    |
 help: you can convert an `isize` to a `u64` and panic if the converted value doesn't fit
    |
@@ -926,7 +1094,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:213:18
    |
 LL |         x_u128 > x_i8;
-   |                  ^^^^ expected `u128`, found `i8`
+   |         ------   ^^^^ expected `u128`, found `i8`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert an `i8` to a `u128` and panic if the converted value doesn't fit
    |
@@ -937,7 +1107,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:215:18
    |
 LL |         x_u128 > x_i16;
-   |                  ^^^^^ expected `u128`, found `i16`
+   |         ------   ^^^^^ expected `u128`, found `i16`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert an `i16` to a `u128` and panic if the converted value doesn't fit
    |
@@ -948,7 +1120,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:217:18
    |
 LL |         x_u128 > x_i32;
-   |                  ^^^^^ expected `u128`, found `i32`
+   |         ------   ^^^^^ expected `u128`, found `i32`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert an `i32` to a `u128` and panic if the converted value doesn't fit
    |
@@ -959,7 +1133,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:219:18
    |
 LL |         x_u128 > x_i64;
-   |                  ^^^^^ expected `u128`, found `i64`
+   |         ------   ^^^^^ expected `u128`, found `i64`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert an `i64` to a `u128` and panic if the converted value doesn't fit
    |
@@ -970,7 +1146,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:221:18
    |
 LL |         x_u128 > x_i128;
-   |                  ^^^^^^ expected `u128`, found `i128`
+   |         ------   ^^^^^^ expected `u128`, found `i128`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert an `i128` to a `u128` and panic if the converted value doesn't fit
    |
@@ -981,7 +1159,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:223:18
    |
 LL |         x_u128 > x_isize;
-   |                  ^^^^^^^ expected `u128`, found `isize`
+   |         ------   ^^^^^^^ expected `u128`, found `isize`
+   |         |
+   |         expected because this is `u128`
    |
 help: you can convert an `isize` to a `u128` and panic if the converted value doesn't fit
    |
@@ -992,7 +1172,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:226:19
    |
 LL |         x_usize > x_i8;
-   |                   ^^^^ expected `usize`, found `i8`
+   |         -------   ^^^^ expected `usize`, found `i8`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert an `i8` to a `usize` and panic if the converted value doesn't fit
    |
@@ -1003,7 +1185,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:228:19
    |
 LL |         x_usize > x_i16;
-   |                   ^^^^^ expected `usize`, found `i16`
+   |         -------   ^^^^^ expected `usize`, found `i16`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert an `i16` to a `usize` and panic if the converted value doesn't fit
    |
@@ -1014,7 +1198,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:230:19
    |
 LL |         x_usize > x_i32;
-   |                   ^^^^^ expected `usize`, found `i32`
+   |         -------   ^^^^^ expected `usize`, found `i32`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert an `i32` to a `usize` and panic if the converted value doesn't fit
    |
@@ -1025,7 +1211,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:232:19
    |
 LL |         x_usize > x_i64;
-   |                   ^^^^^ expected `usize`, found `i64`
+   |         -------   ^^^^^ expected `usize`, found `i64`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert an `i64` to a `usize` and panic if the converted value doesn't fit
    |
@@ -1036,7 +1224,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:234:19
    |
 LL |         x_usize > x_i128;
-   |                   ^^^^^^ expected `usize`, found `i128`
+   |         -------   ^^^^^^ expected `usize`, found `i128`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert an `i128` to a `usize` and panic if the converted value doesn't fit
    |
@@ -1047,7 +1237,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:236:19
    |
 LL |         x_usize > x_isize;
-   |                   ^^^^^^^ expected `usize`, found `isize`
+   |         -------   ^^^^^^^ expected `usize`, found `isize`
+   |         |
+   |         expected because this is `usize`
    |
 help: you can convert an `isize` to a `usize` and panic if the converted value doesn't fit
    |
@@ -1058,7 +1250,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:242:16
    |
 LL |         x_i8 > x_u8;
-   |                ^^^^ expected `i8`, found `u8`
+   |         ----   ^^^^ expected `i8`, found `u8`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert a `u8` to an `i8` and panic if the converted value doesn't fit
    |
@@ -1069,7 +1263,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:244:16
    |
 LL |         x_i8 > x_u16;
-   |                ^^^^^ expected `i8`, found `u16`
+   |         ----   ^^^^^ expected `i8`, found `u16`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert a `u16` to an `i8` and panic if the converted value doesn't fit
    |
@@ -1080,7 +1276,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:246:16
    |
 LL |         x_i8 > x_u32;
-   |                ^^^^^ expected `i8`, found `u32`
+   |         ----   ^^^^^ expected `i8`, found `u32`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert a `u32` to an `i8` and panic if the converted value doesn't fit
    |
@@ -1091,7 +1289,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:248:16
    |
 LL |         x_i8 > x_u64;
-   |                ^^^^^ expected `i8`, found `u64`
+   |         ----   ^^^^^ expected `i8`, found `u64`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert a `u64` to an `i8` and panic if the converted value doesn't fit
    |
@@ -1102,7 +1302,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:250:16
    |
 LL |         x_i8 > x_u128;
-   |                ^^^^^^ expected `i8`, found `u128`
+   |         ----   ^^^^^^ expected `i8`, found `u128`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert a `u128` to an `i8` and panic if the converted value doesn't fit
    |
@@ -1113,7 +1315,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:252:16
    |
 LL |         x_i8 > x_usize;
-   |                ^^^^^^^ expected `i8`, found `usize`
+   |         ----   ^^^^^^^ expected `i8`, found `usize`
+   |         |
+   |         expected because this is `i8`
    |
 help: you can convert a `usize` to an `i8` and panic if the converted value doesn't fit
    |
@@ -1124,7 +1328,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:255:17
    |
 LL |         x_i16 > x_u8;
-   |                 ^^^^ expected `i16`, found `u8`
+   |         -----   ^^^^ expected `i16`, found `u8`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert a `u8` to an `i16`
    |
@@ -1135,7 +1341,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:257:17
    |
 LL |         x_i16 > x_u16;
-   |                 ^^^^^ expected `i16`, found `u16`
+   |         -----   ^^^^^ expected `i16`, found `u16`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert a `u16` to an `i16` and panic if the converted value doesn't fit
    |
@@ -1146,7 +1354,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:259:17
    |
 LL |         x_i16 > x_u32;
-   |                 ^^^^^ expected `i16`, found `u32`
+   |         -----   ^^^^^ expected `i16`, found `u32`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert a `u32` to an `i16` and panic if the converted value doesn't fit
    |
@@ -1157,7 +1367,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:261:17
    |
 LL |         x_i16 > x_u64;
-   |                 ^^^^^ expected `i16`, found `u64`
+   |         -----   ^^^^^ expected `i16`, found `u64`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert a `u64` to an `i16` and panic if the converted value doesn't fit
    |
@@ -1168,7 +1380,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:263:17
    |
 LL |         x_i16 > x_u128;
-   |                 ^^^^^^ expected `i16`, found `u128`
+   |         -----   ^^^^^^ expected `i16`, found `u128`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert a `u128` to an `i16` and panic if the converted value doesn't fit
    |
@@ -1179,7 +1393,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:265:17
    |
 LL |         x_i16 > x_usize;
-   |                 ^^^^^^^ expected `i16`, found `usize`
+   |         -----   ^^^^^^^ expected `i16`, found `usize`
+   |         |
+   |         expected because this is `i16`
    |
 help: you can convert a `usize` to an `i16` and panic if the converted value doesn't fit
    |
@@ -1190,7 +1406,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:268:17
    |
 LL |         x_i32 > x_u8;
-   |                 ^^^^ expected `i32`, found `u8`
+   |         -----   ^^^^ expected `i32`, found `u8`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert a `u8` to an `i32`
    |
@@ -1201,7 +1419,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:270:17
    |
 LL |         x_i32 > x_u16;
-   |                 ^^^^^ expected `i32`, found `u16`
+   |         -----   ^^^^^ expected `i32`, found `u16`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert a `u16` to an `i32`
    |
@@ -1212,7 +1432,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:272:17
    |
 LL |         x_i32 > x_u32;
-   |                 ^^^^^ expected `i32`, found `u32`
+   |         -----   ^^^^^ expected `i32`, found `u32`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit
    |
@@ -1223,7 +1445,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:274:17
    |
 LL |         x_i32 > x_u64;
-   |                 ^^^^^ expected `i32`, found `u64`
+   |         -----   ^^^^^ expected `i32`, found `u64`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert a `u64` to an `i32` and panic if the converted value doesn't fit
    |
@@ -1234,7 +1458,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:276:17
    |
 LL |         x_i32 > x_u128;
-   |                 ^^^^^^ expected `i32`, found `u128`
+   |         -----   ^^^^^^ expected `i32`, found `u128`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert a `u128` to an `i32` and panic if the converted value doesn't fit
    |
@@ -1245,7 +1471,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:278:17
    |
 LL |         x_i32 > x_usize;
-   |                 ^^^^^^^ expected `i32`, found `usize`
+   |         -----   ^^^^^^^ expected `i32`, found `usize`
+   |         |
+   |         expected because this is `i32`
    |
 help: you can convert a `usize` to an `i32` and panic if the converted value doesn't fit
    |
@@ -1256,7 +1484,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:281:17
    |
 LL |         x_i64 > x_u8;
-   |                 ^^^^ expected `i64`, found `u8`
+   |         -----   ^^^^ expected `i64`, found `u8`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert a `u8` to an `i64`
    |
@@ -1267,7 +1497,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:283:17
    |
 LL |         x_i64 > x_u16;
-   |                 ^^^^^ expected `i64`, found `u16`
+   |         -----   ^^^^^ expected `i64`, found `u16`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert a `u16` to an `i64`
    |
@@ -1278,7 +1510,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:285:17
    |
 LL |         x_i64 > x_u32;
-   |                 ^^^^^ expected `i64`, found `u32`
+   |         -----   ^^^^^ expected `i64`, found `u32`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert a `u32` to an `i64`
    |
@@ -1289,7 +1523,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:287:17
    |
 LL |         x_i64 > x_u64;
-   |                 ^^^^^ expected `i64`, found `u64`
+   |         -----   ^^^^^ expected `i64`, found `u64`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert a `u64` to an `i64` and panic if the converted value doesn't fit
    |
@@ -1300,7 +1536,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:289:17
    |
 LL |         x_i64 > x_u128;
-   |                 ^^^^^^ expected `i64`, found `u128`
+   |         -----   ^^^^^^ expected `i64`, found `u128`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert a `u128` to an `i64` and panic if the converted value doesn't fit
    |
@@ -1311,7 +1549,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:291:17
    |
 LL |         x_i64 > x_usize;
-   |                 ^^^^^^^ expected `i64`, found `usize`
+   |         -----   ^^^^^^^ expected `i64`, found `usize`
+   |         |
+   |         expected because this is `i64`
    |
 help: you can convert a `usize` to an `i64` and panic if the converted value doesn't fit
    |
@@ -1322,7 +1562,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:294:18
    |
 LL |         x_i128 > x_u8;
-   |                  ^^^^ expected `i128`, found `u8`
+   |         ------   ^^^^ expected `i128`, found `u8`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert a `u8` to an `i128`
    |
@@ -1333,7 +1575,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:296:18
    |
 LL |         x_i128 > x_u16;
-   |                  ^^^^^ expected `i128`, found `u16`
+   |         ------   ^^^^^ expected `i128`, found `u16`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert a `u16` to an `i128`
    |
@@ -1344,7 +1588,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:298:18
    |
 LL |         x_i128 > x_u32;
-   |                  ^^^^^ expected `i128`, found `u32`
+   |         ------   ^^^^^ expected `i128`, found `u32`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert a `u32` to an `i128`
    |
@@ -1355,7 +1601,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:300:18
    |
 LL |         x_i128 > x_u64;
-   |                  ^^^^^ expected `i128`, found `u64`
+   |         ------   ^^^^^ expected `i128`, found `u64`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert a `u64` to an `i128`
    |
@@ -1366,7 +1614,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:302:18
    |
 LL |         x_i128 > x_u128;
-   |                  ^^^^^^ expected `i128`, found `u128`
+   |         ------   ^^^^^^ expected `i128`, found `u128`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert a `u128` to an `i128` and panic if the converted value doesn't fit
    |
@@ -1377,7 +1627,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:304:18
    |
 LL |         x_i128 > x_usize;
-   |                  ^^^^^^^ expected `i128`, found `usize`
+   |         ------   ^^^^^^^ expected `i128`, found `usize`
+   |         |
+   |         expected because this is `i128`
    |
 help: you can convert a `usize` to an `i128` and panic if the converted value doesn't fit
    |
@@ -1388,7 +1640,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:307:19
    |
 LL |         x_isize > x_u8;
-   |                   ^^^^ expected `isize`, found `u8`
+   |         -------   ^^^^ expected `isize`, found `u8`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert a `u8` to an `isize`
    |
@@ -1399,7 +1653,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:309:19
    |
 LL |         x_isize > x_u16;
-   |                   ^^^^^ expected `isize`, found `u16`
+   |         -------   ^^^^^ expected `isize`, found `u16`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert a `u16` to an `isize` and panic if the converted value doesn't fit
    |
@@ -1410,7 +1666,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:311:19
    |
 LL |         x_isize > x_u32;
-   |                   ^^^^^ expected `isize`, found `u32`
+   |         -------   ^^^^^ expected `isize`, found `u32`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert a `u32` to an `isize` and panic if the converted value doesn't fit
    |
@@ -1421,7 +1679,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:313:19
    |
 LL |         x_isize > x_u64;
-   |                   ^^^^^ expected `isize`, found `u64`
+   |         -------   ^^^^^ expected `isize`, found `u64`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert a `u64` to an `isize` and panic if the converted value doesn't fit
    |
@@ -1432,7 +1692,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:315:19
    |
 LL |         x_isize > x_u128;
-   |                   ^^^^^^ expected `isize`, found `u128`
+   |         -------   ^^^^^^ expected `isize`, found `u128`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert a `u128` to an `isize` and panic if the converted value doesn't fit
    |
@@ -1443,7 +1705,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-binop.rs:317:19
    |
 LL |         x_isize > x_usize;
-   |                   ^^^^^^^ expected `isize`, found `usize`
+   |         -------   ^^^^^^^ expected `isize`, found `usize`
+   |         |
+   |         expected because this is `isize`
    |
 help: you can convert a `usize` to an `isize` and panic if the converted value doesn't fit
    |
diff --git a/src/test/ui/numeric/numeric-cast-no-fix.stderr b/src/test/ui/numeric/numeric-cast-no-fix.stderr
index e4843206de1..c244e479d24 100644
--- a/src/test/ui/numeric/numeric-cast-no-fix.stderr
+++ b/src/test/ui/numeric/numeric-cast-no-fix.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:10:15
    |
 LL |     x_usize > -1_isize;
-   |               ^^^^^^^^ expected `usize`, found `isize`
+   |     -------   ^^^^^^^^ expected `usize`, found `isize`
+   |     |
+   |     expected because this is `usize`
    |
    = note: `-1_isize` cannot fit into type `usize`
 
@@ -10,7 +12,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:12:14
    |
 LL |     x_u128 > -1_isize;
-   |              ^^^^^^^^ expected `u128`, found `isize`
+   |     ------   ^^^^^^^^ expected `u128`, found `isize`
+   |     |
+   |     expected because this is `u128`
    |
    = note: `-1_isize` cannot fit into type `u128`
 
@@ -18,7 +22,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:14:13
    |
 LL |     x_u64 > -1_isize;
-   |             ^^^^^^^^ expected `u64`, found `isize`
+   |     -----   ^^^^^^^^ expected `u64`, found `isize`
+   |     |
+   |     expected because this is `u64`
    |
    = note: `-1_isize` cannot fit into type `u64`
 
@@ -26,7 +32,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:16:13
    |
 LL |     x_u32 > -1_isize;
-   |             ^^^^^^^^ expected `u32`, found `isize`
+   |     -----   ^^^^^^^^ expected `u32`, found `isize`
+   |     |
+   |     expected because this is `u32`
    |
    = note: `-1_isize` cannot fit into type `u32`
 
@@ -34,7 +42,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:18:13
    |
 LL |     x_u16 > -1_isize;
-   |             ^^^^^^^^ expected `u16`, found `isize`
+   |     -----   ^^^^^^^^ expected `u16`, found `isize`
+   |     |
+   |     expected because this is `u16`
    |
    = note: `-1_isize` cannot fit into type `u16`
 
@@ -42,7 +52,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:20:12
    |
 LL |     x_u8 > -1_isize;
-   |            ^^^^^^^^ expected `u8`, found `isize`
+   |     ----   ^^^^^^^^ expected `u8`, found `isize`
+   |     |
+   |     expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `isize`, matching the type of `-1_isize`
    |
@@ -53,7 +65,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:23:15
    |
 LL |     x_usize > -1_i128;
-   |               ^^^^^^^ expected `usize`, found `i128`
+   |     -------   ^^^^^^^ expected `usize`, found `i128`
+   |     |
+   |     expected because this is `usize`
    |
    = note: `-1_i128` cannot fit into type `usize`
 
@@ -61,7 +75,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:25:14
    |
 LL |     x_u128 > -1_i128;
-   |              ^^^^^^^ expected `u128`, found `i128`
+   |     ------   ^^^^^^^ expected `u128`, found `i128`
+   |     |
+   |     expected because this is `u128`
    |
    = note: `-1_i128` cannot fit into type `u128`
 
@@ -69,7 +85,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:27:13
    |
 LL |     x_u64 > -1_i128;
-   |             ^^^^^^^ expected `u64`, found `i128`
+   |     -----   ^^^^^^^ expected `u64`, found `i128`
+   |     |
+   |     expected because this is `u64`
    |
 help: you can convert `x_u64` from `u64` to `i128`, matching the type of `-1_i128`
    |
@@ -80,7 +98,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:29:13
    |
 LL |     x_u32 > -1_i128;
-   |             ^^^^^^^ expected `u32`, found `i128`
+   |     -----   ^^^^^^^ expected `u32`, found `i128`
+   |     |
+   |     expected because this is `u32`
    |
 help: you can convert `x_u32` from `u32` to `i128`, matching the type of `-1_i128`
    |
@@ -91,7 +111,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:31:13
    |
 LL |     x_u16 > -1_i128;
-   |             ^^^^^^^ expected `u16`, found `i128`
+   |     -----   ^^^^^^^ expected `u16`, found `i128`
+   |     |
+   |     expected because this is `u16`
    |
 help: you can convert `x_u16` from `u16` to `i128`, matching the type of `-1_i128`
    |
@@ -102,7 +124,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:33:12
    |
 LL |     x_u8 > -1_i128;
-   |            ^^^^^^^ expected `u8`, found `i128`
+   |     ----   ^^^^^^^ expected `u8`, found `i128`
+   |     |
+   |     expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `i128`, matching the type of `-1_i128`
    |
@@ -113,7 +137,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:36:15
    |
 LL |     x_usize > -1_i64;
-   |               ^^^^^^ expected `usize`, found `i64`
+   |     -------   ^^^^^^ expected `usize`, found `i64`
+   |     |
+   |     expected because this is `usize`
    |
    = note: `-1_i64` cannot fit into type `usize`
 
@@ -121,7 +147,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:38:14
    |
 LL |     x_u128 > -1_i64;
-   |              ^^^^^^ expected `u128`, found `i64`
+   |     ------   ^^^^^^ expected `u128`, found `i64`
+   |     |
+   |     expected because this is `u128`
    |
    = note: `-1_i64` cannot fit into type `u128`
 
@@ -129,7 +157,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:40:13
    |
 LL |     x_u64 > -1_i64;
-   |             ^^^^^^ expected `u64`, found `i64`
+   |     -----   ^^^^^^ expected `u64`, found `i64`
+   |     |
+   |     expected because this is `u64`
    |
    = note: `-1_i64` cannot fit into type `u64`
 
@@ -137,7 +167,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:42:13
    |
 LL |     x_u32 > -1_i64;
-   |             ^^^^^^ expected `u32`, found `i64`
+   |     -----   ^^^^^^ expected `u32`, found `i64`
+   |     |
+   |     expected because this is `u32`
    |
 help: you can convert `x_u32` from `u32` to `i64`, matching the type of `-1_i64`
    |
@@ -148,7 +180,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:44:13
    |
 LL |     x_u16 > -1_i64;
-   |             ^^^^^^ expected `u16`, found `i64`
+   |     -----   ^^^^^^ expected `u16`, found `i64`
+   |     |
+   |     expected because this is `u16`
    |
 help: you can convert `x_u16` from `u16` to `i64`, matching the type of `-1_i64`
    |
@@ -159,7 +193,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:46:12
    |
 LL |     x_u8 > -1_i64;
-   |            ^^^^^^ expected `u8`, found `i64`
+   |     ----   ^^^^^^ expected `u8`, found `i64`
+   |     |
+   |     expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `i64`, matching the type of `-1_i64`
    |
@@ -170,7 +206,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:49:15
    |
 LL |     x_usize > -1_i32;
-   |               ^^^^^^ expected `usize`, found `i32`
+   |     -------   ^^^^^^ expected `usize`, found `i32`
+   |     |
+   |     expected because this is `usize`
    |
    = note: `-1_i32` cannot fit into type `usize`
 
@@ -178,7 +216,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:51:14
    |
 LL |     x_u128 > -1_i32;
-   |              ^^^^^^ expected `u128`, found `i32`
+   |     ------   ^^^^^^ expected `u128`, found `i32`
+   |     |
+   |     expected because this is `u128`
    |
    = note: `-1_i32` cannot fit into type `u128`
 
@@ -186,7 +226,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:53:13
    |
 LL |     x_u64 > -1_i32;
-   |             ^^^^^^ expected `u64`, found `i32`
+   |     -----   ^^^^^^ expected `u64`, found `i32`
+   |     |
+   |     expected because this is `u64`
    |
    = note: `-1_i32` cannot fit into type `u64`
 
@@ -194,7 +236,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:55:13
    |
 LL |     x_u32 > -1_i32;
-   |             ^^^^^^ expected `u32`, found `i32`
+   |     -----   ^^^^^^ expected `u32`, found `i32`
+   |     |
+   |     expected because this is `u32`
    |
    = note: `-1_i32` cannot fit into type `u32`
 
@@ -202,7 +246,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:57:13
    |
 LL |     x_u16 > -1_i32;
-   |             ^^^^^^ expected `u16`, found `i32`
+   |     -----   ^^^^^^ expected `u16`, found `i32`
+   |     |
+   |     expected because this is `u16`
    |
 help: you can convert `x_u16` from `u16` to `i32`, matching the type of `-1_i32`
    |
@@ -213,7 +259,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:59:12
    |
 LL |     x_u8 > -1_i32;
-   |            ^^^^^^ expected `u8`, found `i32`
+   |     ----   ^^^^^^ expected `u8`, found `i32`
+   |     |
+   |     expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `i32`, matching the type of `-1_i32`
    |
@@ -224,7 +272,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:62:15
    |
 LL |     x_usize > -1_i16;
-   |               ^^^^^^ expected `usize`, found `i16`
+   |     -------   ^^^^^^ expected `usize`, found `i16`
+   |     |
+   |     expected because this is `usize`
    |
    = note: `-1_i16` cannot fit into type `usize`
 
@@ -232,7 +282,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:64:14
    |
 LL |     x_u128 > -1_i16;
-   |              ^^^^^^ expected `u128`, found `i16`
+   |     ------   ^^^^^^ expected `u128`, found `i16`
+   |     |
+   |     expected because this is `u128`
    |
    = note: `-1_i16` cannot fit into type `u128`
 
@@ -240,7 +292,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:66:13
    |
 LL |     x_u64 > -1_i16;
-   |             ^^^^^^ expected `u64`, found `i16`
+   |     -----   ^^^^^^ expected `u64`, found `i16`
+   |     |
+   |     expected because this is `u64`
    |
    = note: `-1_i16` cannot fit into type `u64`
 
@@ -248,7 +302,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:68:13
    |
 LL |     x_u32 > -1_i16;
-   |             ^^^^^^ expected `u32`, found `i16`
+   |     -----   ^^^^^^ expected `u32`, found `i16`
+   |     |
+   |     expected because this is `u32`
    |
    = note: `-1_i16` cannot fit into type `u32`
 
@@ -256,7 +312,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:70:13
    |
 LL |     x_u16 > -1_i16;
-   |             ^^^^^^ expected `u16`, found `i16`
+   |     -----   ^^^^^^ expected `u16`, found `i16`
+   |     |
+   |     expected because this is `u16`
    |
    = note: `-1_i16` cannot fit into type `u16`
 
@@ -264,7 +322,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:72:12
    |
 LL |     x_u8 > -1_i16;
-   |            ^^^^^^ expected `u8`, found `i16`
+   |     ----   ^^^^^^ expected `u8`, found `i16`
+   |     |
+   |     expected because this is `u8`
    |
 help: you can convert `x_u8` from `u8` to `i16`, matching the type of `-1_i16`
    |
@@ -275,7 +335,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:75:15
    |
 LL |     x_usize > -1_i8;
-   |               ^^^^^ expected `usize`, found `i8`
+   |     -------   ^^^^^ expected `usize`, found `i8`
+   |     |
+   |     expected because this is `usize`
    |
    = note: `-1_i8` cannot fit into type `usize`
 
@@ -283,7 +345,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:77:14
    |
 LL |     x_u128 > -1_i8;
-   |              ^^^^^ expected `u128`, found `i8`
+   |     ------   ^^^^^ expected `u128`, found `i8`
+   |     |
+   |     expected because this is `u128`
    |
    = note: `-1_i8` cannot fit into type `u128`
 
@@ -291,7 +355,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:79:13
    |
 LL |     x_u64 > -1_i8;
-   |             ^^^^^ expected `u64`, found `i8`
+   |     -----   ^^^^^ expected `u64`, found `i8`
+   |     |
+   |     expected because this is `u64`
    |
    = note: `-1_i8` cannot fit into type `u64`
 
@@ -299,7 +365,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:81:13
    |
 LL |     x_u32 > -1_i8;
-   |             ^^^^^ expected `u32`, found `i8`
+   |     -----   ^^^^^ expected `u32`, found `i8`
+   |     |
+   |     expected because this is `u32`
    |
    = note: `-1_i8` cannot fit into type `u32`
 
@@ -307,7 +375,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:83:13
    |
 LL |     x_u16 > -1_i8;
-   |             ^^^^^ expected `u16`, found `i8`
+   |     -----   ^^^^^ expected `u16`, found `i8`
+   |     |
+   |     expected because this is `u16`
    |
    = note: `-1_i8` cannot fit into type `u16`
 
@@ -315,7 +385,9 @@ error[E0308]: mismatched types
   --> $DIR/numeric-cast-no-fix.rs:85:12
    |
 LL |     x_u8 > -1_i8;
-   |            ^^^^^ expected `u8`, found `i8`
+   |     ----   ^^^^^ expected `u8`, found `i8`
+   |     |
+   |     expected because this is `u8`
    |
    = note: `-1_i8` cannot fit into type `u8`
 
diff --git a/src/test/ui/on-unimplemented/sum.rs b/src/test/ui/on-unimplemented/sum.rs
new file mode 100644
index 00000000000..4f1c521d9fe
--- /dev/null
+++ b/src/test/ui/on-unimplemented/sum.rs
@@ -0,0 +1,9 @@
+// <https://github.com/rust-lang/rust/issues/105184>
+
+fn main() {
+    vec![(), ()].iter().sum::<i32>();
+    //~^ ERROR
+
+    vec![(), ()].iter().product::<i32>();
+    //~^ ERROR
+}
diff --git a/src/test/ui/on-unimplemented/sum.stderr b/src/test/ui/on-unimplemented/sum.stderr
new file mode 100644
index 00000000000..0c99e63f0e5
--- /dev/null
+++ b/src/test/ui/on-unimplemented/sum.stderr
@@ -0,0 +1,39 @@
+error[E0277]: a value of type `i32` cannot be made by summing an iterator over elements of type `&()`
+  --> $DIR/sum.rs:4:5
+   |
+LL |     vec![(), ()].iter().sum::<i32>();
+   |     ^^^^^^^^^^^^^^^^^^^ --- required by a bound introduced by this call
+   |     |
+   |     value of type `i32` cannot be made by summing a `std::iter::Iterator<Item=&()>`
+   |
+   = help: the trait `Sum<&()>` is not implemented for `i32`
+   = help: the following other types implement trait `Sum<A>`:
+             <i32 as Sum<&'a i32>>
+             <i32 as Sum>
+note: required by a bound in `std::iter::Iterator::sum`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |         S: Sum<Self::Item>,
+   |            ^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::sum`
+
+error[E0277]: a value of type `i32` cannot be made by multiplying all elements of type `&()` from an iterator
+  --> $DIR/sum.rs:7:5
+   |
+LL |     vec![(), ()].iter().product::<i32>();
+   |     ^^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
+   |     |
+   |     value of type `i32` cannot be made by multiplying all elements from a `std::iter::Iterator<Item=&()>`
+   |
+   = help: the trait `Product<&()>` is not implemented for `i32`
+   = help: the following other types implement trait `Product<A>`:
+             <i32 as Product<&'a i32>>
+             <i32 as Product>
+note: required by a bound in `std::iter::Iterator::product`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |         P: Product<Self::Item>,
+   |            ^^^^^^^^^^^^^^^^^^^ required by this bound in `std::iter::Iterator::product`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/parser/bare-struct-body.stderr b/src/test/ui/parser/bare-struct-body.stderr
index c77992b2c34..7d17ea59647 100644
--- a/src/test/ui/parser/bare-struct-body.stderr
+++ b/src/test/ui/parser/bare-struct-body.stderr
@@ -34,7 +34,9 @@ error[E0308]: mismatched types
   --> $DIR/bare-struct-body.rs:11:14
    |
 LL |     x.val == 42;
-   |              ^^ expected `()`, found integer
+   |     -----    ^^ expected `()`, found integer
+   |     |
+   |     expected because this is `()`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/parser/chained-comparison-suggestion.stderr b/src/test/ui/parser/chained-comparison-suggestion.stderr
index 694b0b6eb02..ae243816d7c 100644
--- a/src/test/ui/parser/chained-comparison-suggestion.stderr
+++ b/src/test/ui/parser/chained-comparison-suggestion.stderr
@@ -123,37 +123,49 @@ error[E0308]: mismatched types
   --> $DIR/chained-comparison-suggestion.rs:4:14
    |
 LL |     1 < 2 <= 3;
-   |              ^ expected `bool`, found integer
+   |     -----    ^ expected `bool`, found integer
+   |     |
+   |     expected because this is `bool`
 
 error[E0308]: mismatched types
   --> $DIR/chained-comparison-suggestion.rs:13:14
    |
 LL |     1 <= 2 < 3;
-   |              ^ expected `bool`, found integer
+   |     ------   ^ expected `bool`, found integer
+   |     |
+   |     expected because this is `bool`
 
 error[E0308]: mismatched types
   --> $DIR/chained-comparison-suggestion.rs:18:15
    |
 LL |     1 <= 2 <= 3;
-   |               ^ expected `bool`, found integer
+   |     ------    ^ expected `bool`, found integer
+   |     |
+   |     expected because this is `bool`
 
 error[E0308]: mismatched types
   --> $DIR/chained-comparison-suggestion.rs:23:14
    |
 LL |     1 > 2 >= 3;
-   |              ^ expected `bool`, found integer
+   |     -----    ^ expected `bool`, found integer
+   |     |
+   |     expected because this is `bool`
 
 error[E0308]: mismatched types
   --> $DIR/chained-comparison-suggestion.rs:36:15
    |
 LL |     1 >= 2 >= 3;
-   |               ^ expected `bool`, found integer
+   |     ------    ^ expected `bool`, found integer
+   |     |
+   |     expected because this is `bool`
 
 error[E0308]: mismatched types
   --> $DIR/chained-comparison-suggestion.rs:49:15
    |
 LL |     1 == 2 == 3;
-   |               ^ expected `bool`, found integer
+   |     ------    ^ expected `bool`, found integer
+   |     |
+   |     expected because this is `bool`
 
 error: aborting due to 17 previous errors
 
diff --git a/src/test/ui/pptypedef.stderr b/src/test/ui/pptypedef.stderr
index 49895f3db4d..08b90b365e3 100644
--- a/src/test/ui/pptypedef.stderr
+++ b/src/test/ui/pptypedef.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/pptypedef.rs:4:37
    |
 LL |     let_in(3u32, |i| { assert!(i == 3i32); });
-   |                                     ^^^^ expected `u32`, found `i32`
+   |                                -    ^^^^ expected `u32`, found `i32`
+   |                                |
+   |                                expected because this is `u32`
    |
 help: change the type of the numeric literal from `i32` to `u32`
    |
@@ -13,7 +15,9 @@ error[E0308]: mismatched types
   --> $DIR/pptypedef.rs:8:37
    |
 LL |     let_in(3i32, |i| { assert!(i == 3u32); });
-   |                                     ^^^^ expected `i32`, found `u32`
+   |                                -    ^^^^ expected `i32`, found `u32`
+   |                                |
+   |                                expected because this is `i32`
    |
 help: change the type of the numeric literal from `u32` to `i32`
    |
diff --git a/src/test/ui/print_type_sizes/async.rs b/src/test/ui/print_type_sizes/async.rs
new file mode 100644
index 00000000000..3491ad5afbc
--- /dev/null
+++ b/src/test/ui/print_type_sizes/async.rs
@@ -0,0 +1,19 @@
+// compile-flags: -Z print-type-sizes
+// edition:2021
+// build-pass
+// ignore-pass
+
+#![feature(start)]
+
+async fn wait() {}
+
+async fn test(arg: [u8; 8192]) {
+    wait().await;
+    drop(arg);
+}
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    let _ = test([0; 8192]);
+    0
+}
diff --git a/src/test/ui/print_type_sizes/async.stdout b/src/test/ui/print_type_sizes/async.stdout
new file mode 100644
index 00000000000..94ad09ef296
--- /dev/null
+++ b/src/test/ui/print_type_sizes/async.stdout
@@ -0,0 +1,34 @@
+print-type-size type: `[async fn body@$DIR/async.rs:10:32: 13:2]`: 16386 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Suspend0`: 16385 bytes
+print-type-size         field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size         field `.arg`: 8192 bytes
+print-type-size         field `.__awaitee`: 1 bytes
+print-type-size     variant `Unresumed`: 8192 bytes
+print-type-size         field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Returned`: 8192 bytes
+print-type-size         field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Panicked`: 8192 bytes
+print-type-size         field `.arg`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size type: `std::mem::ManuallyDrop<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes
+print-type-size     field `.value`: 8192 bytes
+print-type-size type: `std::mem::MaybeUninit<[u8; 8192]>`: 8192 bytes, alignment: 1 bytes
+print-type-size     variant `MaybeUninit`: 8192 bytes
+print-type-size         field `.uninit`: 0 bytes
+print-type-size         field `.value`: 8192 bytes
+print-type-size type: `[async fn body@$DIR/async.rs:8:17: 8:19]`: 1 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Unresumed`: 0 bytes
+print-type-size     variant `Returned`: 0 bytes
+print-type-size     variant `Panicked`: 0 bytes
+print-type-size type: `std::mem::ManuallyDrop<[async fn body@$DIR/async.rs:8:17: 8:19]>`: 1 bytes, alignment: 1 bytes
+print-type-size     field `.value`: 1 bytes
+print-type-size type: `std::mem::MaybeUninit<[async fn body@$DIR/async.rs:8:17: 8:19]>`: 1 bytes, alignment: 1 bytes
+print-type-size     variant `MaybeUninit`: 1 bytes
+print-type-size         field `.uninit`: 0 bytes
+print-type-size         field `.value`: 1 bytes
+print-type-size type: `std::task::Poll<()>`: 1 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Ready`: 0 bytes
+print-type-size         field `.0`: 0 bytes
+print-type-size     variant `Pending`: 0 bytes
diff --git a/src/test/ui/print_type_sizes/generator.rs b/src/test/ui/print_type_sizes/generator.rs
new file mode 100644
index 00000000000..a46db612104
--- /dev/null
+++ b/src/test/ui/print_type_sizes/generator.rs
@@ -0,0 +1,20 @@
+// compile-flags: -Z print-type-sizes
+// build-pass
+// ignore-pass
+
+#![feature(start, generators, generator_trait)]
+
+use std::ops::Generator;
+
+fn generator<const C: usize>(array: [u8; C]) -> impl Generator<Yield = (), Return = ()> {
+    move |()| {
+        yield ();
+        let _ = array;
+    }
+}
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    let _ = generator([0; 8192]);
+    0
+}
diff --git a/src/test/ui/print_type_sizes/generator.stdout b/src/test/ui/print_type_sizes/generator.stdout
new file mode 100644
index 00000000000..28d4a6e6cff
--- /dev/null
+++ b/src/test/ui/print_type_sizes/generator.stdout
@@ -0,0 +1,10 @@
+print-type-size type: `[generator@$DIR/generator.rs:10:5: 10:14]`: 8193 bytes, alignment: 1 bytes
+print-type-size     discriminant: 1 bytes
+print-type-size     variant `Unresumed`: 8192 bytes
+print-type-size         field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Returned`: 8192 bytes
+print-type-size         field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Panicked`: 8192 bytes
+print-type-size         field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
+print-type-size     variant `Suspend0`: 8192 bytes
+print-type-size         field `.array`: 8192 bytes, offset: 0 bytes, alignment: 1 bytes
diff --git a/src/test/ui/proc-macro/attr-invalid-exprs.stderr b/src/test/ui/proc-macro/attr-invalid-exprs.stderr
index bcb54df0eca..f96939bb6ef 100644
--- a/src/test/ui/proc-macro/attr-invalid-exprs.stderr
+++ b/src/test/ui/proc-macro/attr-invalid-exprs.stderr
@@ -8,21 +8,25 @@ error: macro expansion ignores token `,` and any following
   --> $DIR/attr-invalid-exprs.rs:15:13
    |
 LL |     let _ = #[duplicate] "Hello, world!";
-   |             ^^^^^^^^^^^^- help: you might be missing a semicolon here: `;`
-   |             |
-   |             caused by the macro expansion here
+   |             ^^^^^^^^^^^^ caused by the macro expansion here
    |
    = note: the usage of `duplicate!` is likely invalid in expression context
+help: you might be missing a semicolon here
+   |
+LL |     let _ = #[duplicate]; "Hello, world!";
+   |                         +
 
 error: macro expansion ignores token `,` and any following
   --> $DIR/attr-invalid-exprs.rs:24:9
    |
 LL |         #[duplicate]
-   |         ^^^^^^^^^^^^- help: you might be missing a semicolon here: `;`
-   |         |
-   |         caused by the macro expansion here
+   |         ^^^^^^^^^^^^ caused by the macro expansion here
    |
    = note: the usage of `duplicate!` is likely invalid in expression context
+help: you might be missing a semicolon here
+   |
+LL |         #[duplicate];
+   |                     +
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/proc-macro/attribute.rs b/src/test/ui/proc-macro/attribute.rs
index 5531b323621..9e40e4d9ba6 100644
--- a/src/test/ui/proc-macro/attribute.rs
+++ b/src/test/ui/proc-macro/attribute.rs
@@ -53,19 +53,19 @@ pub fn foo11(input: TokenStream) -> TokenStream { input }
 pub fn foo12(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d13, attributes("a"))]
-//~^ ERROR: not a meta item
+//~^ ERROR: attribute must be a meta item, not a literal
 pub fn foo13(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d14, attributes(a = ""))]
-//~^ ERROR: must only be one word
+//~^ ERROR: attribute must only be a single word
 pub fn foo14(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d15, attributes(m::a))]
-//~^ ERROR: must only be one word
+//~^ ERROR: attribute must only be a single word
 pub fn foo15(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d16, attributes(a(b)))]
-//~^ ERROR: must only be one word
+//~^ ERROR: attribute must only be a single word
 pub fn foo16(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d17, attributes(self))]
diff --git a/src/test/ui/proc-macro/attribute.stderr b/src/test/ui/proc-macro/attribute.stderr
index 021e7cad09b..3269aaf7f91 100644
--- a/src/test/ui/proc-macro/attribute.stderr
+++ b/src/test/ui/proc-macro/attribute.stderr
@@ -70,25 +70,25 @@ error: attribute must be of form: `attributes(foo, bar)`
 LL | #[proc_macro_derive(d12, attributes)]
    |                          ^^^^^^^^^^
 
-error: not a meta item
+error: attribute must be a meta item, not a literal
   --> $DIR/attribute.rs:55:37
    |
 LL | #[proc_macro_derive(d13, attributes("a"))]
    |                                     ^^^
 
-error: must only be one word
+error: attribute must only be a single word
   --> $DIR/attribute.rs:59:37
    |
 LL | #[proc_macro_derive(d14, attributes(a = ""))]
    |                                     ^^^^^^
 
-error: must only be one word
+error: attribute must only be a single word
   --> $DIR/attribute.rs:63:37
    |
 LL | #[proc_macro_derive(d15, attributes(m::a))]
    |                                     ^^^^
 
-error: must only be one word
+error: attribute must only be a single word
   --> $DIR/attribute.rs:67:37
    |
 LL | #[proc_macro_derive(d16, attributes(a(b)))]
diff --git a/src/test/ui/proc-macro/expand-expr.stderr b/src/test/ui/proc-macro/expand-expr.stderr
index c6c4695fd9c..0004f2fe17f 100644
--- a/src/test/ui/proc-macro/expand-expr.stderr
+++ b/src/test/ui/proc-macro/expand-expr.stderr
@@ -26,21 +26,25 @@ error: macro expansion ignores token `hello` and any following
   --> $DIR/expand-expr.rs:115:47
    |
 LL | expand_expr_is!("string", echo_tts!("string"; hello));
-   |                           --------------------^^^^^-- help: you might be missing a semicolon here: `;`
-   |                           |
-   |                           caused by the macro expansion here
+   |                           --------------------^^^^^- caused by the macro expansion here
    |
    = note: the usage of `echo_tts!` is likely invalid in expression context
+help: you might be missing a semicolon here
+   |
+LL | expand_expr_is!("string", echo_tts!("string"; hello););
+   |                                                     +
 
 error: macro expansion ignores token `;` and any following
   --> $DIR/expand-expr.rs:116:44
    |
 LL | expand_expr_is!("string", echo_pm!("string"; hello));
-   |                           -----------------^-------- help: you might be missing a semicolon here: `;`
-   |                           |
-   |                           caused by the macro expansion here
+   |                           -----------------^------- caused by the macro expansion here
    |
    = note: the usage of `echo_pm!` is likely invalid in expression context
+help: you might be missing a semicolon here
+   |
+LL | expand_expr_is!("string", echo_pm!("string"; hello););
+   |                                                    +
 
 error: recursion limit reached while expanding `recursive_expand!`
   --> $DIR/expand-expr.rs:124:16
diff --git a/src/test/ui/recursion/issue-83150.stderr b/src/test/ui/recursion/issue-83150.stderr
index 4d00a708313..dde8ad1b6b3 100644
--- a/src/test/ui/recursion/issue-83150.stderr
+++ b/src/test/ui/recursion/issue-83150.stderr
@@ -12,7 +12,7 @@ LL |     func(&mut iter.map(|x| x + 1))
 error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>: Iterator`
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`)
-   = note: required for `&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>` to implement `Iterator`
+   = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<..., ...>, ...>, ...>, ...>, ...>, ...>, ...>` to implement `Iterator`
    = note: the full type name has been written to '$TEST_BUILD_DIR/recursion/issue-83150/issue-83150.long-type-hash.txt'
 
 error: aborting due to previous error; 1 warning emitted
diff --git a/src/test/ui/regions/issue-102374.rs b/src/test/ui/regions/issue-102374.rs
index e0a1164211a..fd71248d9cb 100644
--- a/src/test/ui/regions/issue-102374.rs
+++ b/src/test/ui/regions/issue-102374.rs
@@ -1,3 +1,4 @@
+// normalize-stderr-test: "long-type-\d+" -> "long-type-hash"
 use std::cell::Cell;
 
 #[rustfmt::skip]
diff --git a/src/test/ui/regions/issue-102374.stderr b/src/test/ui/regions/issue-102374.stderr
index 31b855c36be..157850693ab 100644
--- a/src/test/ui/regions/issue-102374.stderr
+++ b/src/test/ui/regions/issue-102374.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-102374.rs:16:5
+  --> $DIR/issue-102374.rs:17:5
    |
 LL | ) -> i32 {
    |      --- expected `i32` because of return type
@@ -7,7 +7,8 @@ LL |     f
    |     ^ expected `i32`, found fn pointer
    |
    = note:    expected type `i32`
-           found fn pointer `for<'z1, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, 'y, 'z, 'z0> fn(Cell<(&'z1 i32, &'a i32, &'b i32, &'c i32, &'d i32, &'e i32, &'f i32, &'g i32, &'h i32, &'i i32, &'j i32, &'k i32, &'l i32, &'m i32, &'n i32, &'o i32, &'p i32, &'q i32, &'r i32, &'s i32, &'t i32, &'u i32, &'v i32, &'w i32, &'x i32, &'y i32, &'z i32, &'z0 i32)>)`
+           found fn pointer `for<'z1, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'l, 'm, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, 'y, 'z, 'z0> fn(Cell<...>)`
+           the full type name has been written to '$TEST_BUILD_DIR/regions/issue-102374/issue-102374.long-type-hash.txt'
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/span/issue-71363.rs b/src/test/ui/span/issue-71363.rs
index bbb4a93623b..f187d0efa84 100644
--- a/src/test/ui/span/issue-71363.rs
+++ b/src/test/ui/span/issue-71363.rs
@@ -1,4 +1,4 @@
-// compile-flags: -Z simulate-remapped-rust-src-base=/rustc/xyz -Z translate-remapped-path-to-local-path=no -Z ui-testing=no
+// compile-flags: -Z simulate-remapped-rust-src-base=/rustc/FAKE_PREFIX -Z translate-remapped-path-to-local-path=no -Z ui-testing=no
 
 struct MyError;
 impl std::error::Error for MyError {}
diff --git a/src/test/ui/span/issue-71363.stderr b/src/test/ui/span/issue-71363.stderr
index 04e2b46c317..6c7ea007ee0 100644
--- a/src/test/ui/span/issue-71363.stderr
+++ b/src/test/ui/span/issue-71363.stderr
@@ -7,6 +7,7 @@ error[E0277]: `MyError` doesn't implement `std::fmt::Display`
   = help: the trait `std::fmt::Display` is not implemented for `MyError`
   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
 note: required by a bound in `std::error::Error`
+ --> $SRC_DIR/core/src/error.rs:LL:COL
 
 error[E0277]: `MyError` doesn't implement `Debug`
  --> $DIR/issue-71363.rs:4:6
@@ -17,6 +18,7 @@ error[E0277]: `MyError` doesn't implement `Debug`
   = help: the trait `Debug` is not implemented for `MyError`
   = note: add `#[derive(Debug)]` to `MyError` or manually `impl Debug for MyError`
 note: required by a bound in `std::error::Error`
+ --> $SRC_DIR/core/src/error.rs:LL:COL
 help: consider annotating `MyError` with `#[derive(Debug)]`
   |
 3 | #[derive(Debug)]
diff --git a/src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr b/src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr
index 4e21d36014c..bc6342004f4 100644
--- a/src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr
+++ b/src/test/ui/suggestions/dont-suggest-try_into-in-macros.stderr
@@ -2,7 +2,10 @@ error[E0308]: mismatched types
   --> $DIR/dont-suggest-try_into-in-macros.rs:2:5
    |
 LL |     assert_eq!(10u64, 10usize);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u64`, found `usize`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     |
+   |     expected `u64`, found `usize`
+   |     expected because this is `u64`
    |
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/suggestions/option-to-bool.stderr b/src/test/ui/suggestions/option-to-bool.stderr
index 57a934b8342..4050c7be82a 100644
--- a/src/test/ui/suggestions/option-to-bool.stderr
+++ b/src/test/ui/suggestions/option-to-bool.stderr
@@ -2,7 +2,9 @@ error[E0308]: mismatched types
   --> $DIR/option-to-bool.rs:4:16
    |
 LL |     if true && x {}
-   |                ^ expected `bool`, found enum `Option`
+   |        ----    ^ expected `bool`, found enum `Option`
+   |        |
+   |        expected because this is `bool`
    |
    = note: expected type `bool`
               found enum `Option<i32>`
diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs b/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs
index 56e8fcff0fc..8db5fa615c0 100644
--- a/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs
+++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs
@@ -1,15 +1,15 @@
 #![feature(rustc_attrs)]
 
 #[rustc_must_implement_one_of(a, a)]
-//~^ Functions names are duplicated
+//~^ functions names are duplicated
 trait Trait {
     fn a() {}
 }
 
 #[rustc_must_implement_one_of(b, a, a, c, b, c)]
-//~^ Functions names are duplicated
-//~| Functions names are duplicated
-//~| Functions names are duplicated
+//~^ functions names are duplicated
+//~| functions names are duplicated
+//~| functions names are duplicated
 trait Trait1 {
     fn a() {}
     fn b() {}
diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr b/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr
index 777beba6182..cd1476a6eb8 100644
--- a/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr
+++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr
@@ -1,34 +1,34 @@
-error: Functions names are duplicated
+error: functions names are duplicated
   --> $DIR/rustc_must_implement_one_of_duplicates.rs:3:31
    |
 LL | #[rustc_must_implement_one_of(a, a)]
    |                               ^  ^
    |
-   = note: All `#[rustc_must_implement_one_of]` arguments must be unique
+   = note: all `#[rustc_must_implement_one_of]` arguments must be unique
 
-error: Functions names are duplicated
+error: functions names are duplicated
   --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:34
    |
 LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)]
    |                                  ^  ^
    |
-   = note: All `#[rustc_must_implement_one_of]` arguments must be unique
+   = note: all `#[rustc_must_implement_one_of]` arguments must be unique
 
-error: Functions names are duplicated
+error: functions names are duplicated
   --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:31
    |
 LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)]
    |                               ^           ^
    |
-   = note: All `#[rustc_must_implement_one_of]` arguments must be unique
+   = note: all `#[rustc_must_implement_one_of]` arguments must be unique
 
-error: Functions names are duplicated
+error: functions names are duplicated
   --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:40
    |
 LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)]
    |                                        ^     ^
    |
-   = note: All `#[rustc_must_implement_one_of]` arguments must be unique
+   = note: all `#[rustc_must_implement_one_of]` arguments must be unique
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs
index 1f896da94db..b1b91966c8d 100644
--- a/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs
+++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs
@@ -1,12 +1,12 @@
 #![feature(rustc_attrs)]
 
 #[rustc_must_implement_one_of(a, b)]
-//~^ Function not found in this trait
-//~| Function not found in this trait
+//~^ function not found in this trait
+//~| function not found in this trait
 trait Tr0 {}
 
 #[rustc_must_implement_one_of(a, b)]
-//~^ Function not found in this trait
+//~^ function not found in this trait
 trait Tr1 {
     fn a() {}
 }
@@ -23,16 +23,16 @@ trait Tr3 {}
 
 #[rustc_must_implement_one_of(A, B)]
 trait Tr4 {
-    const A: u8 = 1; //~ Not a function
+    const A: u8 = 1; //~ not a function
 
-    type B; //~ Not a function
+    type B; //~ not a function
 }
 
 #[rustc_must_implement_one_of(a, b)]
 trait Tr5 {
-    fn a(); //~ This function doesn't have a default implementation
+    fn a(); //~ function doesn't have a default implementation
 
-    fn b(); //~ This function doesn't have a default implementation
+    fn b(); //~ function doesn't have a default implementation
 }
 
 #[rustc_must_implement_one_of(abc, xyz)]
diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr
index 869184f0d1a..38e692521ca 100644
--- a/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr
+++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr
@@ -22,19 +22,19 @@ LL |
 LL | struct Struct {}
    | ---------------- not a trait
 
-error: Function not found in this trait
+error: function not found in this trait
   --> $DIR/rustc_must_implement_one_of_misuse.rs:3:31
    |
 LL | #[rustc_must_implement_one_of(a, b)]
    |                               ^
 
-error: Function not found in this trait
+error: function not found in this trait
   --> $DIR/rustc_must_implement_one_of_misuse.rs:3:34
    |
 LL | #[rustc_must_implement_one_of(a, b)]
    |                                  ^
 
-error: Function not found in this trait
+error: function not found in this trait
   --> $DIR/rustc_must_implement_one_of_misuse.rs:8:34
    |
 LL | #[rustc_must_implement_one_of(a, b)]
@@ -46,7 +46,7 @@ error: the `#[rustc_must_implement_one_of]` attribute must be used with at least
 LL | #[rustc_must_implement_one_of(a)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: Not a function
+error: not a function
   --> $DIR/rustc_must_implement_one_of_misuse.rs:26:5
    |
 LL |     const A: u8 = 1;
@@ -57,9 +57,9 @@ note: required by this annotation
    |
 LL | #[rustc_must_implement_one_of(A, B)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: All `#[rustc_must_implement_one_of]` arguments must be associated function names
+   = note: all `#[rustc_must_implement_one_of]` arguments must be associated function names
 
-error: Not a function
+error: not a function
   --> $DIR/rustc_must_implement_one_of_misuse.rs:28:5
    |
 LL |     type B;
@@ -70,9 +70,9 @@ note: required by this annotation
    |
 LL | #[rustc_must_implement_one_of(A, B)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: All `#[rustc_must_implement_one_of]` arguments must be associated function names
+   = note: all `#[rustc_must_implement_one_of]` arguments must be associated function names
 
-error: This function doesn't have a default implementation
+error: function doesn't have a default implementation
   --> $DIR/rustc_must_implement_one_of_misuse.rs:33:5
    |
 LL |     fn a();
@@ -84,7 +84,7 @@ note: required by this annotation
 LL | #[rustc_must_implement_one_of(a, b)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: This function doesn't have a default implementation
+error: function doesn't have a default implementation
   --> $DIR/rustc_must_implement_one_of_misuse.rs:35:5
    |
 LL |     fn b();
diff --git a/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr b/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr
index a74d2524996..1f18c5daf66 100644
--- a/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr
+++ b/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr
@@ -17,7 +17,7 @@ error[E0275]: overflow evaluating the requirement `(): Sized`
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "512"]` attribute to your crate (`issue_91949_hangs_on_recursion`)
    = note: required for `std::iter::Empty<()>` to implement `Iterator`
    = note: 171 redundant requirements hidden
-   = note: required for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<..., ...>>, ...>>` to implement `Iterator`
+   = note: required for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<..., ...>>, ...>>, ...>>` to implement `Iterator`
    = note: the full type name has been written to '$TEST_BUILD_DIR/traits/issue-91949-hangs-on-recursion/issue-91949-hangs-on-recursion.long-type-hash.txt'
 
 error: aborting due to previous error; 1 warning emitted
diff --git a/src/test/ui/type/type-check/assignment-in-if.stderr b/src/test/ui/type/type-check/assignment-in-if.stderr
index 8ab08e25e30..9f4558adab1 100644
--- a/src/test/ui/type/type-check/assignment-in-if.stderr
+++ b/src/test/ui/type/type-check/assignment-in-if.stderr
@@ -68,7 +68,9 @@ error[E0308]: mismatched types
   --> $DIR/assignment-in-if.rs:44:18
    |
 LL |     if x == x && x = x && x == x {
-   |                  ^ expected `bool`, found `usize`
+   |        ------    ^ expected `bool`, found `usize`
+   |        |
+   |        expected because this is `bool`
 
 error[E0308]: mismatched types
   --> $DIR/assignment-in-if.rs:44:22
@@ -91,7 +93,9 @@ error[E0308]: mismatched types
   --> $DIR/assignment-in-if.rs:51:28
    |
 LL |     if x == x && x == x && x = x {
-   |                            ^ expected `bool`, found `usize`
+   |        ----------------    ^ expected `bool`, found `usize`
+   |        |
+   |        expected because this is `bool`
 
 error[E0308]: mismatched types
   --> $DIR/assignment-in-if.rs:51:8
diff --git a/src/test/ui/type/type-params-in-different-spaces-1.stderr b/src/test/ui/type/type-params-in-different-spaces-1.stderr
index 4e73e10a301..7529f25bd8e 100644
--- a/src/test/ui/type/type-params-in-different-spaces-1.stderr
+++ b/src/test/ui/type/type-params-in-different-spaces-1.stderr
@@ -6,7 +6,9 @@ LL | trait BrokenAdd: Copy + Add<Output=Self> {
 LL |     fn broken_add<T>(&self, rhs: T) -> Self {
    |                   - found type parameter
 LL |         *self + rhs
-   |                 ^^^ expected type parameter `Self`, found type parameter `T`
+   |         -----   ^^^ expected type parameter `Self`, found type parameter `T`
+   |         |
+   |         expected because this is `Self`
    |
    = note: expected type parameter `Self`
               found type parameter `T`
diff --git a/src/test/ui/wrong-mul-method-signature.stderr b/src/test/ui/wrong-mul-method-signature.stderr
index 9f8896f01ee..8338f61b22a 100644
--- a/src/test/ui/wrong-mul-method-signature.stderr
+++ b/src/test/ui/wrong-mul-method-signature.stderr
@@ -38,7 +38,9 @@ error[E0308]: mismatched types
   --> $DIR/wrong-mul-method-signature.rs:63:45
    |
 LL |     let x: Vec2 = Vec2 { x: 1.0, y: 2.0 } * 2.0; // trait had reversed order
-   |                                             ^^^ expected struct `Vec2`, found floating-point number
+   |                   -----------------------   ^^^ expected struct `Vec2`, found floating-point number
+   |                   |
+   |                   expected because this is `Vec2`
 
 error[E0308]: mismatched types
   --> $DIR/wrong-mul-method-signature.rs:63:19
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject f6e737b1e3386adb89333bf06a01f68a91ac530
+Subproject 70898e522116f6c23971e2a554b2dc85fd4c84c
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index 17b0507682a..9263f051972 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -386,14 +386,12 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
             Node::Expr(parent_expr) => {
                 if let Some((callee_def_id, call_substs, recv, call_args)) = get_callee_substs_and_args(cx, parent_expr)
                 {
-                    if Some(callee_def_id) == cx.tcx.lang_items().into_future_fn() {
-                        return false;
-                    }
-
                     let fn_sig = cx.tcx.fn_sig(callee_def_id).skip_binder();
                     if let Some(arg_index) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == expr.hir_id)
                         && let Some(param_ty) = fn_sig.inputs().get(arg_index)
                         && let ty::Param(ParamTy { index: param_index , ..}) = param_ty.kind()
+                        // https://github.com/rust-lang/rust-clippy/issues/9504 and https://github.com/rust-lang/rust-clippy/issues/10021
+                        && (*param_index as usize) < call_substs.len()
                     {
                         if fn_sig
                             .inputs()
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 480e8e55cf3..e053a9dc888 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
@@ -303,7 +303,6 @@ fn check_terminator<'tcx>(
 
         TerminatorKind::SwitchInt {
             discr,
-            switch_ty: _,
             targets: _,
         } => check_operand(tcx, discr, span, body),
 
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 64d97e91442..c5767a79538 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -906,6 +906,7 @@ pub fn make_test_description<R: Read>(
     let has_asm_support = config.has_asm_support();
     let has_asan = util::ASAN_SUPPORTED_TARGETS.contains(&&*config.target);
     let has_cfi = util::CFI_SUPPORTED_TARGETS.contains(&&*config.target);
+    let has_kcfi = util::KCFI_SUPPORTED_TARGETS.contains(&&*config.target);
     let has_lsan = util::LSAN_SUPPORTED_TARGETS.contains(&&*config.target);
     let has_msan = util::MSAN_SUPPORTED_TARGETS.contains(&&*config.target);
     let has_tsan = util::TSAN_SUPPORTED_TARGETS.contains(&&*config.target);
@@ -957,6 +958,7 @@ pub fn make_test_description<R: Read>(
             && config.parse_name_directive(ln, "needs-sanitizer-support");
         ignore |= !has_asan && config.parse_name_directive(ln, "needs-sanitizer-address");
         ignore |= !has_cfi && config.parse_name_directive(ln, "needs-sanitizer-cfi");
+        ignore |= !has_kcfi && config.parse_name_directive(ln, "needs-sanitizer-kcfi");
         ignore |= !has_lsan && config.parse_name_directive(ln, "needs-sanitizer-leak");
         ignore |= !has_msan && config.parse_name_directive(ln, "needs-sanitizer-memory");
         ignore |= !has_tsan && config.parse_name_directive(ln, "needs-sanitizer-thread");
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index e07b71a7c47..1542b1c17ad 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -3542,6 +3542,8 @@ impl<'test> TestCx<'test> {
             option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").map(PathBuf::from),
             // Virtual `/rustc/$sha` coming from download-rustc:
             std::env::var_os("FAKE_DOWNLOAD_RUSTC_PREFIX").map(PathBuf::from),
+            // Tests using -Zsimulate-remapped-rust-src-base should use this fake path
+            Some("/rustc/FAKE_PREFIX".into()),
         ];
         for base_dir in source_bases {
             if let Some(base_dir) = base_dir {
diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs
index ec36f1e4fb7..ccba313ee35 100644
--- a/src/tools/compiletest/src/util.rs
+++ b/src/tools/compiletest/src/util.rs
@@ -42,6 +42,8 @@ pub const CFI_SUPPORTED_TARGETS: &[&str] = &[
     "x86_64-unknown-netbsd",
 ];
 
+pub const KCFI_SUPPORTED_TARGETS: &[&str] = &["aarch64-linux-none", "x86_64-linux-none"];
+
 pub const LSAN_SUPPORTED_TARGETS: &[&str] = &[
     // FIXME: currently broken, see #88132
     // "aarch64-apple-darwin",
diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs
index 10e6e252e94..f896a337f42 100644
--- a/src/tools/miri/src/borrow_tracker/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/mod.rs
@@ -11,7 +11,6 @@ use rustc_target::abi::Size;
 
 use crate::*;
 pub mod stacked_borrows;
-use stacked_borrows::diagnostics::RetagCause;
 
 pub type CallId = NonZeroU64;
 
@@ -265,11 +264,19 @@ impl GlobalStateInner {
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
-    fn retag(&mut self, kind: RetagKind, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+    fn retag_ptr_value(&mut self, kind: RetagKind, val: &ImmTy<'tcx, Provenance>) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
         let this = self.eval_context_mut();
         let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
         match method {
-            BorrowTrackerMethod::StackedBorrows => this.sb_retag(kind, place),
+            BorrowTrackerMethod::StackedBorrows => this.sb_retag_ptr_value(kind, val),
+        }
+    }
+
+    fn retag_place_contents(&mut self, kind: RetagKind, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+        let this = self.eval_context_mut();
+        let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
+        match method {
+            BorrowTrackerMethod::StackedBorrows => this.sb_retag_place_contents(kind, place),
         }
     }
 
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
index 9a7b38b13a3..24b3489e0d1 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
@@ -459,10 +459,10 @@ impl<'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'history, 'ecx, 'mir, 'tcx> {
             Operation::Dealloc(_) => format!(" due to deallocation"),
             Operation::Access(AccessOp { kind, tag, .. }) =>
                 format!(" due to {kind:?} access for {tag:?}"),
-            Operation::Retag(RetagOp { orig_tag, permission, .. }) => {
+            Operation::Retag(RetagOp { orig_tag, permission, new_tag, .. }) => {
                 let permission = permission
                     .expect("start_grant should set the current permission before popping a tag");
-                format!(" due to {permission:?} retag from {orig_tag:?}")
+                format!(" due to {permission:?} retag from {orig_tag:?} (that retag created {new_tag:?})")
             }
         };
 
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
index bcac873251f..ffbc0086402 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -1,9 +1,13 @@
 //! Implements "Stacked Borrows".  See <https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md>
 //! for further information.
 
+pub mod diagnostics;
+mod item;
+mod stack;
+
 use log::trace;
 use std::cmp;
-use std::fmt::{self, Write};
+use std::fmt::Write;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::mir::{Mutability, RetagKind};
@@ -15,15 +19,13 @@ use rustc_target::abi::{Abi, Size};
 
 use crate::borrow_tracker::{
     stacked_borrows::diagnostics::{AllocHistory, DiagnosticCx, DiagnosticCxBuilder, TagHistory},
-    AccessKind, GlobalStateInner, ProtectorKind, RetagCause, RetagFields,
+    AccessKind, GlobalStateInner, ProtectorKind, RetagFields,
 };
 use crate::*;
 
-mod item;
+use diagnostics::RetagCause;
 pub use item::{Item, Permission};
-mod stack;
 pub use stack::Stack;
-pub mod diagnostics;
 
 pub type AllocState = Stacks;
 
@@ -40,30 +42,104 @@ pub struct Stacks {
     modified_since_last_gc: bool,
 }
 
-/// Indicates which kind of reference is being created.
-/// Used by high-level `reborrow` to compute which permissions to grant to the
-/// new pointer.
-#[derive(Copy, Clone, Hash, PartialEq, Eq)]
-enum RefKind {
-    /// `Box`.
-    Box,
-    /// `&mut`.
-    Unique { two_phase: bool },
-    /// `&` with or without interior mutability.
-    Shared,
-    /// `*mut`/`*const` (raw pointers).
-    Raw { mutable: bool },
+/// Indicates which permissions to grant to the retagged pointer.
+#[derive(Clone, Debug)]
+enum NewPermission {
+    Uniform {
+        perm: Permission,
+        access: Option<AccessKind>,
+        protector: Option<ProtectorKind>,
+    },
+    FreezeSensitive {
+        freeze_perm: Permission,
+        freeze_access: Option<AccessKind>,
+        freeze_protector: Option<ProtectorKind>,
+        nonfreeze_perm: Permission,
+        nonfreeze_access: Option<AccessKind>,
+        // nonfreeze_protector must always be None
+    },
 }
 
-impl fmt::Display for RefKind {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+impl NewPermission {
+    /// A key function: determine the permissions to grant at a retag for the given kind of
+    /// reference/pointer.
+    fn from_ref_ty<'tcx>(
+        ty: ty::Ty<'tcx>,
+        kind: RetagKind,
+        cx: &crate::MiriInterpCx<'_, 'tcx>,
+    ) -> Self {
+        let protector = (kind == RetagKind::FnEntry).then_some(ProtectorKind::StrongProtector);
+        match ty.kind() {
+            ty::Ref(_, pointee, Mutability::Mut) => {
+                if kind == RetagKind::TwoPhase {
+                    // We mostly just give up on 2phase-borrows, and treat these exactly like raw pointers.
+                    assert!(protector.is_none()); // RetagKind can't be both FnEntry and TwoPhase.
+                    NewPermission::Uniform {
+                        perm: Permission::SharedReadWrite,
+                        access: None,
+                        protector: None,
+                    }
+                } else if pointee.is_unpin(*cx.tcx, cx.param_env()) {
+                    // A regular full mutable reference.
+                    NewPermission::Uniform {
+                        perm: Permission::Unique,
+                        access: Some(AccessKind::Write),
+                        protector,
+                    }
+                } else {
+                    NewPermission::Uniform {
+                        perm: Permission::SharedReadWrite,
+                        // FIXME: We emit `dereferenceable` for `!Unpin` mutable references, so we
+                        // should do fake accesses here. But then we run into
+                        // <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>, so for now
+                        // we don't do that.
+                        access: None,
+                        protector,
+                    }
+                }
+            }
+            ty::RawPtr(ty::TypeAndMut { mutbl: Mutability::Mut, .. }) => {
+                assert!(protector.is_none()); // RetagKind can't be both FnEntry and Raw.
+                // Mutable raw pointer. No access, not protected.
+                NewPermission::Uniform {
+                    perm: Permission::SharedReadWrite,
+                    access: None,
+                    protector: None,
+                }
+            }
+            ty::Ref(_, _pointee, Mutability::Not) => {
+                NewPermission::FreezeSensitive {
+                    freeze_perm: Permission::SharedReadOnly,
+                    freeze_access: Some(AccessKind::Read),
+                    freeze_protector: protector,
+                    nonfreeze_perm: Permission::SharedReadWrite,
+                    // Inside UnsafeCell, this does *not* count as an access, as there
+                    // might actually be mutable references further up the stack that
+                    // we have to keep alive.
+                    nonfreeze_access: None,
+                    // We do not protect inside UnsafeCell.
+                    // This fixes https://github.com/rust-lang/rust/issues/55005.
+                }
+            }
+            ty::RawPtr(ty::TypeAndMut { mutbl: Mutability::Not, .. }) => {
+                assert!(protector.is_none()); // RetagKind can't be both FnEntry and Raw.
+                // `*const T`, when freshly created, are read-only in the frozen part.
+                NewPermission::FreezeSensitive {
+                    freeze_perm: Permission::SharedReadOnly,
+                    freeze_access: Some(AccessKind::Read),
+                    freeze_protector: None,
+                    nonfreeze_perm: Permission::SharedReadWrite,
+                    nonfreeze_access: None,
+                }
+            }
+            _ => unreachable!(),
+        }
+    }
+
+    fn protector(&self) -> Option<ProtectorKind> {
         match self {
-            RefKind::Box => write!(f, "Box"),
-            RefKind::Unique { two_phase: false } => write!(f, "unique reference"),
-            RefKind::Unique { two_phase: true } => write!(f, "unique reference (two-phase)"),
-            RefKind::Shared => write!(f, "shared reference"),
-            RefKind::Raw { mutable: true } => write!(f, "raw (mutable) pointer"),
-            RefKind::Raw { mutable: false } => write!(f, "raw (constant) pointer"),
+            NewPermission::Uniform { protector, .. } => *protector,
+            NewPermission::FreezeSensitive { freeze_protector, .. } => *freeze_protector,
         }
     }
 }
@@ -518,10 +594,9 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
         &mut self,
         place: &MPlaceTy<'tcx, Provenance>,
         size: Size,
-        kind: RefKind,
-        retag_cause: RetagCause, // What caused this retag, for diagnostics only
+        new_perm: NewPermission,
         new_tag: BorTag,
-        protect: Option<ProtectorKind>,
+        retag_cause: RetagCause, // What caused this retag, for diagnostics only
     ) -> InterpResult<'tcx, Option<AllocId>> {
         let this = self.eval_context_mut();
 
@@ -532,20 +607,16 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
             let global = this.machine.borrow_tracker.as_ref().unwrap().borrow();
             let ty = place.layout.ty;
             if global.tracked_pointer_tags.contains(&new_tag) {
-                let mut kind_str = format!("{kind}");
-                match kind {
-                    RefKind::Unique { two_phase: false }
-                        if !ty.is_unpin(*this.tcx, this.param_env()) =>
-                    {
-                        write!(kind_str, " (!Unpin pointee type {ty})").unwrap()
-                    },
-                    RefKind::Shared
-                        if !ty.is_freeze(*this.tcx, this.param_env()) =>
-                    {
-                        write!(kind_str, " (!Freeze pointee type {ty})").unwrap()
-                    },
-                    _ => write!(kind_str, " (pointee type {ty})").unwrap(),
-                };
+                let mut kind_str = String::new();
+                match new_perm {
+                    NewPermission::Uniform { perm, .. } =>
+                        write!(kind_str, "{perm:?} permission").unwrap(),
+                    NewPermission::FreezeSensitive { freeze_perm, .. } if ty.is_freeze(*this.tcx, this.param_env()) =>
+                        write!(kind_str, "{freeze_perm:?} permission").unwrap(),
+                    NewPermission::FreezeSensitive { freeze_perm, nonfreeze_perm, .. }  =>
+                        write!(kind_str, "{freeze_perm:?}/{nonfreeze_perm:?} permission for frozen/non-frozen parts").unwrap(),
+                }
+                write!(kind_str, " (pointee type {ty})").unwrap();
                 this.emit_diagnostic(NonHaltingDiagnostic::CreatedPointerTag(
                     new_tag.inner(),
                     Some(kind_str),
@@ -579,7 +650,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
                     );
                     let mut dcx = dcx.build(&mut stacked_borrows.history, base_offset);
                     dcx.log_creation();
-                    if protect.is_some() {
+                    if new_perm.protector().is_some() {
                         dcx.log_protector();
                     }
                 },
@@ -592,8 +663,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
 
         if size == Size::ZERO {
             trace!(
-                "reborrow of size 0: {} reference {:?} derived from {:?} (pointee {})",
-                kind,
+                "reborrow of size 0: reference {:?} derived from {:?} (pointee {})",
                 new_tag,
                 place.ptr,
                 place.layout.ty,
@@ -630,8 +700,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
         }
 
         trace!(
-            "reborrow: {} reference {:?} derived from {:?} (pointee {}): {:?}, size {}",
-            kind,
+            "reborrow: reference {:?} derived from {:?} (pointee {}): {:?}, size {}",
             new_tag,
             orig_tag,
             place.layout.ty,
@@ -639,7 +708,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
             size.bytes()
         );
 
-        if let Some(protect) = protect {
+        if let Some(protect) = new_perm.protector() {
             // See comment in `Stack::item_invalidated` for why we store the tag twice.
             this.frame_mut().extra.borrow_tracker.as_mut().unwrap().protected_tags.push(new_tag);
             this.machine
@@ -651,30 +720,45 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
                 .insert(new_tag, protect);
         }
 
-        // Update the stacks.
-        // Make sure that raw pointers and mutable shared references are reborrowed "weak":
-        // There could be existing unique pointers reborrowed from them that should remain valid!
-        let (perm, access) = match kind {
-            RefKind::Unique { two_phase } => {
-                // Permission is Unique only if the type is `Unpin` and this is not twophase
-                if !two_phase && place.layout.ty.is_unpin(*this.tcx, this.param_env()) {
-                    (Permission::Unique, Some(AccessKind::Write))
-                } else {
-                    // FIXME: We emit `dereferenceable` for `!Unpin` mutable references, so we
-                    // should do fake accesses here. But then we run into
-                    // <https://github.com/rust-lang/unsafe-code-guidelines/issues/381>, so for now
-                    // we don't do that.
-                    (Permission::SharedReadWrite, None)
+        // Update the stacks, according to the new permission information we are given.
+        match new_perm {
+            NewPermission::Uniform { perm, access, protector } => {
+                assert!(perm != Permission::SharedReadOnly);
+                // Here we can avoid `borrow()` calls because we have mutable references.
+                // Note that this asserts that the allocation is mutable -- but since we are creating a
+                // mutable pointer, that seems reasonable.
+                let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc_id)?;
+                let stacked_borrows = alloc_extra.borrow_tracker_sb_mut().get_mut();
+                let item = Item::new(new_tag, perm, protector.is_some());
+                let range = alloc_range(base_offset, size);
+                let global = machine.borrow_tracker.as_ref().unwrap().borrow();
+                let dcx = DiagnosticCxBuilder::retag(
+                    machine,
+                    retag_cause,
+                    new_tag,
+                    orig_tag,
+                    alloc_range(base_offset, size),
+                );
+                stacked_borrows.for_each(range, dcx, |stack, dcx, exposed_tags| {
+                    stack.grant(orig_tag, item, access, &global, dcx, exposed_tags)
+                })?;
+                drop(global);
+                if let Some(access) = access {
+                    assert_eq!(access, AccessKind::Write);
+                    // Make sure the data race model also knows about this.
+                    if let Some(data_race) = alloc_extra.data_race.as_mut() {
+                        data_race.write(alloc_id, range, machine)?;
+                    }
                 }
             }
-            RefKind::Box => (Permission::Unique, Some(AccessKind::Write)),
-            RefKind::Raw { mutable: true } => {
-                // Creating a raw ptr does not count as an access
-                (Permission::SharedReadWrite, None)
-            }
-            RefKind::Shared | RefKind::Raw { mutable: false } => {
-                // Shared references and *const are a whole different kind of game, the
-                // permission is not uniform across the entire range!
+            NewPermission::FreezeSensitive {
+                freeze_perm,
+                freeze_access,
+                freeze_protector,
+                nonfreeze_perm,
+                nonfreeze_access,
+            } => {
+                // The permission is not uniform across the entire range!
                 // We need a frozen-sensitive reborrow.
                 // We have to use shared references to alloc/memory_extra here since
                 // `visit_freeze_sensitive` needs to access the global state.
@@ -684,22 +768,12 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
                     // Adjust range.
                     range.start += base_offset;
                     // We are only ever `SharedReadOnly` inside the frozen bits.
-                    let (perm, access) = if frozen {
-                        (Permission::SharedReadOnly, Some(AccessKind::Read))
-                    } else {
-                        // Inside UnsafeCell, this does *not* count as an access, as there
-                        // might actually be mutable references further up the stack that
-                        // we have to keep alive.
-                        (Permission::SharedReadWrite, None)
-                    };
-                    let protected = if frozen {
-                        protect.is_some()
+                    let (perm, access, protector) = if frozen {
+                        (freeze_perm, freeze_access, freeze_protector)
                     } else {
-                        // We do not protect inside UnsafeCell.
-                        // This fixes https://github.com/rust-lang/rust/issues/55005.
-                        false
+                        (nonfreeze_perm, nonfreeze_access, None)
                     };
-                    let item = Item::new(new_tag, perm, protected);
+                    let item = Item::new(new_tag, perm, protector.is_some());
                     let global = this.machine.borrow_tracker.as_ref().unwrap().borrow();
                     let dcx = DiagnosticCxBuilder::retag(
                         &this.machine,
@@ -721,34 +795,6 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
                     }
                     Ok(())
                 })?;
-                return Ok(Some(alloc_id));
-            }
-        };
-
-        // Here we can avoid `borrow()` calls because we have mutable references.
-        // Note that this asserts that the allocation is mutable -- but since we are creating a
-        // mutable pointer, that seems reasonable.
-        let (alloc_extra, machine) = this.get_alloc_extra_mut(alloc_id)?;
-        let stacked_borrows = alloc_extra.borrow_tracker_sb_mut().get_mut();
-        let item = Item::new(new_tag, perm, protect.is_some());
-        let range = alloc_range(base_offset, size);
-        let global = machine.borrow_tracker.as_ref().unwrap().borrow();
-        let dcx = DiagnosticCxBuilder::retag(
-            machine,
-            retag_cause,
-            new_tag,
-            orig_tag,
-            alloc_range(base_offset, size),
-        );
-        stacked_borrows.for_each(range, dcx, |stack, dcx, exposed_tags| {
-            stack.grant(orig_tag, item, access, &global, dcx, exposed_tags)
-        })?;
-        drop(global);
-        if let Some(access) = access {
-            assert_eq!(access, AccessKind::Write);
-            // Make sure the data race model also knows about this.
-            if let Some(data_race) = alloc_extra.data_race.as_mut() {
-                data_race.write(alloc_id, range, machine)?;
             }
         }
 
@@ -760,9 +806,8 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
     fn sb_retag_reference(
         &mut self,
         val: &ImmTy<'tcx, Provenance>,
-        kind: RefKind,
-        retag_cause: RetagCause, // What caused this retag, for diagnostics only
-        protect: Option<ProtectorKind>,
+        new_perm: NewPermission,
+        cause: RetagCause, // What caused this retag, for diagnostics only
     ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
         let this = self.eval_context_mut();
         // We want a place for where the ptr *points to*, so we get one.
@@ -780,7 +825,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
         let new_tag = this.machine.borrow_tracker.as_mut().unwrap().get_mut().new_ptr();
 
         // Reborrow.
-        let alloc_id = this.sb_reborrow(&place, size, kind, retag_cause, new_tag, protect)?;
+        let alloc_id = this.sb_reborrow(&place, size, new_perm, new_tag, cause)?;
 
         // Adjust pointer.
         let new_place = place.map_provenance(|p| {
@@ -807,7 +852,22 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
-    fn sb_retag(
+    fn sb_retag_ptr_value(
+        &mut self,
+        kind: RetagKind,
+        val: &ImmTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+        let this = self.eval_context_mut();
+        let new_perm = NewPermission::from_ref_ty(val.layout.ty, kind, this);
+        let retag_cause = match kind {
+            RetagKind::TwoPhase { .. } => RetagCause::TwoPhase,
+            RetagKind::FnEntry => unreachable!(),
+            RetagKind::Raw | RetagKind::Default => RetagCause::Normal,
+        };
+        this.sb_retag_reference(&val, new_perm, retag_cause)
+    }
+
+    fn sb_retag_place_contents(
         &mut self,
         kind: RetagKind,
         place: &PlaceTy<'tcx, Provenance>,
@@ -815,9 +875,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let this = self.eval_context_mut();
         let retag_fields = this.machine.borrow_tracker.as_mut().unwrap().get_mut().retag_fields;
         let retag_cause = match kind {
-            RetagKind::TwoPhase { .. } => RetagCause::TwoPhase,
+            RetagKind::Raw | RetagKind::TwoPhase { .. } => unreachable!(), // these can only happen in `retag_ptr_value`
             RetagKind::FnEntry => RetagCause::FnEntry,
-            RetagKind::Raw | RetagKind::Default => RetagCause::Normal,
+            RetagKind::Default => RetagCause::Normal,
         };
         let mut visitor = RetagVisitor { ecx: this, kind, retag_cause, retag_fields };
         return visitor.visit_value(place);
@@ -831,15 +891,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         }
         impl<'ecx, 'mir, 'tcx> RetagVisitor<'ecx, 'mir, 'tcx> {
             #[inline(always)] // yes this helps in our benchmarks
-            fn retag_place(
+            fn retag_ptr_inplace(
                 &mut self,
                 place: &PlaceTy<'tcx, Provenance>,
-                ref_kind: RefKind,
+                new_perm: NewPermission,
                 retag_cause: RetagCause,
-                protector: Option<ProtectorKind>,
             ) -> InterpResult<'tcx> {
                 let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?;
-                let val = self.ecx.sb_retag_reference(&val, ref_kind, retag_cause, protector)?;
+                let val = self.ecx.sb_retag_reference(&val, new_perm, retag_cause)?;
                 self.ecx.write_immediate(*val, place)?;
                 Ok(())
             }
@@ -856,13 +915,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
             fn visit_box(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
                 // Boxes get a weak protectors, since they may be deallocated.
-                self.retag_place(
-                    place,
-                    RefKind::Box,
-                    self.retag_cause,
-                    /*protector*/
-                    (self.kind == RetagKind::FnEntry).then_some(ProtectorKind::WeakProtector),
-                )
+                let new_perm = NewPermission::Uniform {
+                    perm: Permission::Unique,
+                    access: Some(AccessKind::Write),
+                    protector: (self.kind == RetagKind::FnEntry)
+                        .then_some(ProtectorKind::WeakProtector),
+                };
+                self.retag_ptr_inplace(place, new_perm, self.retag_cause)
             }
 
             fn visit_value(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
@@ -876,36 +935,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
                 // Check the type of this value to see what to do with it (retag, or recurse).
                 match place.layout.ty.kind() {
-                    ty::Ref(_, _, mutbl) => {
-                        let ref_kind = match mutbl {
-                            Mutability::Mut =>
-                                RefKind::Unique { two_phase: self.kind == RetagKind::TwoPhase },
-                            Mutability::Not => RefKind::Shared,
-                        };
-                        self.retag_place(
-                            place,
-                            ref_kind,
-                            self.retag_cause,
-                            /*protector*/
-                            (self.kind == RetagKind::FnEntry)
-                                .then_some(ProtectorKind::StrongProtector),
-                        )?;
+                    ty::Ref(..) => {
+                        let new_perm =
+                            NewPermission::from_ref_ty(place.layout.ty, self.kind, self.ecx);
+                        self.retag_ptr_inplace(place, new_perm, self.retag_cause)?;
                     }
-                    ty::RawPtr(tym) => {
-                        // We definitely do *not* want to recurse into raw pointers -- wide raw
-                        // pointers have fields, and for dyn Trait pointees those can have reference
-                        // type!
-                        if self.kind == RetagKind::Raw {
-                            // Raw pointers need to be enabled.
-                            self.retag_place(
-                                place,
-                                RefKind::Raw { mutable: tym.mutbl == Mutability::Mut },
-                                self.retag_cause,
-                                /*protector*/ None,
-                            )?;
-                        }
+                    ty::RawPtr(..) => {
+                        // We do *not* want to recurse into raw pointers -- wide raw pointers have
+                        // fields, and for dyn Trait pointees those can have reference type!
                     }
-                    _ if place.layout.ty.ty_adt_def().is_some_and(|adt| adt.is_box()) => {
+                    ty::Adt(adt, _) if adt.is_box() => {
                         // Recurse for boxes, they require some tricky handling and will end up in `visit_box` above.
                         // (Yes this means we technically also recursively retag the allocator itself
                         // even if field retagging is not enabled. *shrug*)
@@ -953,12 +992,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         let ptr_layout = this.layout_of(this.tcx.mk_mut_ptr(return_place.layout.ty))?;
         let val = ImmTy::from_immediate(return_place.to_ref(this), ptr_layout);
         // Reborrow it. With protection! That is part of the point.
-        let val = this.sb_retag_reference(
-            &val,
-            RefKind::Unique { two_phase: false },
-            RetagCause::FnReturn,
-            /*protector*/ Some(ProtectorKind::StrongProtector),
-        )?;
+        let new_perm = NewPermission::Uniform {
+            perm: Permission::Unique,
+            access: Some(AccessKind::Write),
+            protector: Some(ProtectorKind::StrongProtector),
+        };
+        let val = this.sb_retag_reference(&val, new_perm, RetagCause::FnReturn)?;
         // And use reborrowed pointer for return place.
         let return_place = this.ref_to_mplace(&val)?;
         this.frame_mut().return_place = return_place.into();
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 074fa032dcc..c22ac50e455 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -63,9 +63,9 @@ impl MachineStopType for TerminationInfo {}
 
 /// Miri specific diagnostics
 pub enum NonHaltingDiagnostic {
-    /// (new_tag, new_kind, (alloc_id, base_offset, orig_tag))
+    /// (new_tag, new_perm, (alloc_id, base_offset, orig_tag))
     ///
-    /// new_kind is `None` for base tags.
+    /// new_perm is `None` for base tags.
     CreatedPointerTag(NonZeroU64, Option<String>, Option<(AllocId, AllocRange, ProvenanceExtra)>),
     /// This `Item` was popped from the borrow stack. The string explains the reason.
     PoppedPointerTag(Item, String),
@@ -364,7 +364,9 @@ fn report_msg<'tcx>(
         if is_local && idx > 0 {
             err.span_note(frame_info.span, &frame_info.to_string());
         } else {
-            err.note(&frame_info.to_string());
+            let sm = sess.source_map();
+            let span = sm.span_to_embeddable_string(frame_info.span);
+            err.note(format!("{frame_info} at {span}"));
         }
     }
 
@@ -393,10 +395,10 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
 
         let msg = match &e {
             CreatedPointerTag(tag, None, _) => format!("created base tag {tag:?}"),
-            CreatedPointerTag(tag, Some(kind), None) => format!("created {tag:?} for {kind}"),
-            CreatedPointerTag(tag, Some(kind), Some((alloc_id, range, orig_tag))) =>
+            CreatedPointerTag(tag, Some(perm), None) => format!("created {tag:?} with {perm} derived from unknown tag"),
+            CreatedPointerTag(tag, Some(perm), Some((alloc_id, range, orig_tag))) =>
                 format!(
-                    "created tag {tag:?} for {kind} at {alloc_id:?}{range:?} derived from {orig_tag:?}"
+                    "created tag {tag:?} with {perm} at {alloc_id:?}{range:?} derived from {orig_tag:?}"
                 ),
             PoppedPointerTag(item, cause) => format!("popped tracked tag for item {item:?}{cause}"),
             CreatedCallId(id) => format!("function call with id {id}"),
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index c110229c985..e5b1eb2e487 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -967,8 +967,9 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         ptr: Pointer<Self::Provenance>,
     ) -> InterpResult<'tcx> {
         match ptr.provenance {
-            Provenance::Concrete { alloc_id, tag } =>
-                intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag),
+            Provenance::Concrete { alloc_id, tag } => {
+                intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag)
+            }
             Provenance::Wildcard => {
                 // No need to do anything for wildcard pointers as
                 // their provenances have already been previously exposed.
@@ -1055,13 +1056,26 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
     }
 
     #[inline(always)]
-    fn retag(
+    fn retag_ptr_value(
+        ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        kind: mir::RetagKind,
+        val: &ImmTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
+        if ecx.machine.borrow_tracker.is_some() {
+            ecx.retag_ptr_value(kind, val)
+        } else {
+            Ok(val.clone())
+        }
+    }
+
+    #[inline(always)]
+    fn retag_place_contents(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         kind: mir::RetagKind,
         place: &PlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
         if ecx.machine.borrow_tracker.is_some() {
-            ecx.retag(kind, place)?;
+            ecx.retag_place_contents(kind, place)?;
         }
         Ok(())
     }
diff --git a/src/tools/miri/tests/fail/abort-terminator.stderr b/src/tools/miri/tests/fail/abort-terminator.stderr
index ec9ce76685b..2d3275f6b19 100644
--- a/src/tools/miri/tests/fail/abort-terminator.stderr
+++ b/src/tools/miri/tests/fail/abort-terminator.stderr
@@ -10,7 +10,7 @@ LL | | }
    | |_^ the program aborted execution
    |
    = note: inside `panic_abort` at $DIR/abort-terminator.rs:LL:CC
-note: inside `main` at $DIR/abort-terminator.rs:LL:CC
+note: inside `main`
   --> $DIR/abort-terminator.rs:LL:CC
    |
 LL |     panic_abort();
diff --git a/src/tools/miri/tests/fail/alloc/deallocate-bad-alignment.stderr b/src/tools/miri/tests/fail/alloc/deallocate-bad-alignment.stderr
index 28439b54b29..095eeeb79de 100644
--- a/src/tools/miri/tests/fail/alloc/deallocate-bad-alignment.stderr
+++ b/src/tools/miri/tests/fail/alloc/deallocate-bad-alignment.stderr
@@ -8,7 +8,7 @@ LL |     unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
-note: inside `main` at $DIR/deallocate-bad-alignment.rs:LL:CC
+note: inside `main`
   --> $DIR/deallocate-bad-alignment.rs:LL:CC
    |
 LL |         dealloc(x, Layout::from_size_align_unchecked(1, 2));
diff --git a/src/tools/miri/tests/fail/alloc/deallocate-bad-size.stderr b/src/tools/miri/tests/fail/alloc/deallocate-bad-size.stderr
index a6ceab1f56f..5fe93c841b2 100644
--- a/src/tools/miri/tests/fail/alloc/deallocate-bad-size.stderr
+++ b/src/tools/miri/tests/fail/alloc/deallocate-bad-size.stderr
@@ -8,7 +8,7 @@ LL |     unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
-note: inside `main` at $DIR/deallocate-bad-size.rs:LL:CC
+note: inside `main`
   --> $DIR/deallocate-bad-size.rs:LL:CC
    |
 LL |         dealloc(x, Layout::from_size_align_unchecked(2, 1));
diff --git a/src/tools/miri/tests/fail/alloc/deallocate-twice.stderr b/src/tools/miri/tests/fail/alloc/deallocate-twice.stderr
index b6c5b6f97ee..fa7a74ee13c 100644
--- a/src/tools/miri/tests/fail/alloc/deallocate-twice.stderr
+++ b/src/tools/miri/tests/fail/alloc/deallocate-twice.stderr
@@ -8,7 +8,7 @@ LL |     unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
-note: inside `main` at $DIR/deallocate-twice.rs:LL:CC
+note: inside `main`
   --> $DIR/deallocate-twice.rs:LL:CC
    |
 LL |         dealloc(x, Layout::from_size_align_unchecked(1, 1));
diff --git a/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr b/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr
index 4ee85add6c2..62ffb8142a3 100644
--- a/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr
+++ b/src/tools/miri/tests/fail/alloc/global_system_mixup.stderr
@@ -9,7 +9,7 @@ LL |         FREE();
    = note: BACKTRACE:
    = note: inside `std::sys::PLATFORM::alloc::<impl std::alloc::GlobalAlloc for std::alloc::System>::dealloc` at RUSTLIB/std/src/sys/PLATFORM/alloc.rs:LL:CC
    = note: inside `<std::alloc::System as std::alloc::Allocator>::deallocate` at RUSTLIB/std/src/alloc.rs:LL:CC
-note: inside `main` at $DIR/global_system_mixup.rs:LL:CC
+note: inside `main`
   --> $DIR/global_system_mixup.rs:LL:CC
    |
 LL |         System.deallocate(ptr, l);
diff --git a/src/tools/miri/tests/fail/alloc/reallocate-bad-size.stderr b/src/tools/miri/tests/fail/alloc/reallocate-bad-size.stderr
index c11b5a85104..24cabb39564 100644
--- a/src/tools/miri/tests/fail/alloc/reallocate-bad-size.stderr
+++ b/src/tools/miri/tests/fail/alloc/reallocate-bad-size.stderr
@@ -8,7 +8,7 @@ LL |     unsafe { __rust_realloc(ptr, layout.size(), layout.align(), new_size) }
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `std::alloc::realloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
-note: inside `main` at $DIR/reallocate-bad-size.rs:LL:CC
+note: inside `main`
   --> $DIR/reallocate-bad-size.rs:LL:CC
    |
 LL |         let _y = realloc(x, Layout::from_size_align_unchecked(2, 1), 1);
diff --git a/src/tools/miri/tests/fail/alloc/reallocate-dangling.stderr b/src/tools/miri/tests/fail/alloc/reallocate-dangling.stderr
index c7db5a72904..b1460bfb763 100644
--- a/src/tools/miri/tests/fail/alloc/reallocate-dangling.stderr
+++ b/src/tools/miri/tests/fail/alloc/reallocate-dangling.stderr
@@ -8,7 +8,7 @@ LL |     unsafe { __rust_realloc(ptr, layout.size(), layout.align(), new_size) }
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `std::alloc::realloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
-note: inside `main` at $DIR/reallocate-dangling.rs:LL:CC
+note: inside `main`
   --> $DIR/reallocate-dangling.rs:LL:CC
    |
 LL |         let _z = realloc(x, Layout::from_size_align_unchecked(1, 1), 1);
diff --git a/src/tools/miri/tests/fail/alloc/stack_free.stderr b/src/tools/miri/tests/fail/alloc/stack_free.stderr
index 44991542b13..b1636050a78 100644
--- a/src/tools/miri/tests/fail/alloc/stack_free.stderr
+++ b/src/tools/miri/tests/fail/alloc/stack_free.stderr
@@ -12,7 +12,7 @@ LL |     unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
    = note: inside `alloc::alloc::box_free::<i32, std::alloc::Global>` at RUSTLIB/alloc/src/alloc.rs:LL:CC
    = note: inside `std::ptr::drop_in_place::<std::boxed::Box<i32>> - shim(Some(std::boxed::Box<i32>))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
    = note: inside `std::mem::drop::<std::boxed::Box<i32>>` at RUSTLIB/core/src/mem/mod.rs:LL:CC
-note: inside `main` at $DIR/stack_free.rs:LL:CC
+note: inside `main`
   --> $DIR/stack_free.rs:LL:CC
    |
 LL |     drop(bad_box);
diff --git a/src/tools/miri/tests/fail/box-cell-alias.stderr b/src/tools/miri/tests/fail/box-cell-alias.stderr
index 83701639976..f57b52c4bda 100644
--- a/src/tools/miri/tests/fail/box-cell-alias.stderr
+++ b/src/tools/miri/tests/fail/box-cell-alias.stderr
@@ -21,7 +21,7 @@ LL |     let res = helper(val, ptr);
    |                      ^^^
    = note: BACKTRACE:
    = note: inside `helper` at $DIR/box-cell-alias.rs:LL:CC
-note: inside `main` at $DIR/box-cell-alias.rs:LL:CC
+note: inside `main`
   --> $DIR/box-cell-alias.rs:LL:CC
    |
 LL |     let res = helper(val, ptr);
diff --git a/src/tools/miri/tests/fail/concurrency/windows_join_detached.stderr b/src/tools/miri/tests/fail/concurrency/windows_join_detached.stderr
index 20f34cf104d..7b297b260d8 100644
--- a/src/tools/miri/tests/fail/concurrency/windows_join_detached.stderr
+++ b/src/tools/miri/tests/fail/concurrency/windows_join_detached.stderr
@@ -10,7 +10,7 @@ LL |         let rc = unsafe { c::WaitForSingleObject(self.handle.as_raw_handle(
    = note: inside `std::sys::PLATFORM::thread::Thread::join` at RUSTLIB/std/src/sys/PLATFORM/thread.rs:LL:CC
    = note: inside `std::thread::JoinInner::<'_, ()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC
    = note: inside `std::thread::JoinHandle::<()>::join` at RUSTLIB/std/src/thread/mod.rs:LL:CC
-note: inside `main` at $DIR/windows_join_detached.rs:LL:CC
+note: inside `main`
   --> $DIR/windows_join_detached.rs:LL:CC
    |
 LL |     thread.join().unwrap();
diff --git a/src/tools/miri/tests/fail/crates/tokio_mvp.stderr b/src/tools/miri/tests/fail/crates/tokio_mvp.stderr
index 5a80d1ac5a9..1e7dfaa7499 100644
--- a/src/tools/miri/tests/fail/crates/tokio_mvp.stderr
+++ b/src/tools/miri/tests/fail/crates/tokio_mvp.stderr
@@ -6,7 +6,7 @@ LL |         let res = syscall!(epoll_create1(libc::EPOLL_CLOEXEC));
    |
    = help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
    = note: BACKTRACE:
-note: inside `main` at $DIR/tokio_mvp.rs:LL:CC
+note: inside `main`
   --> $DIR/tokio_mvp.rs:LL:CC
    |
 LL | #[tokio::main]
diff --git a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr
index 72e5f20f924..2ba8116cadc 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/storage_dead_dangling.stderr
@@ -8,7 +8,7 @@ LL |     unsafe { &mut *(LEAK as *mut i32) };
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `evil` at $DIR/storage_dead_dangling.rs:LL:CC
-note: inside `main` at $DIR/storage_dead_dangling.rs:LL:CC
+note: inside `main`
   --> $DIR/storage_dead_dangling.rs:LL:CC
    |
 LL |     evil();
diff --git a/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr b/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr
index 5de27108ab6..0075f877b29 100644
--- a/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr
+++ b/src/tools/miri/tests/fail/data_race/stack_pop_race.stderr
@@ -8,7 +8,7 @@ LL | }
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `race` at $DIR/stack_pop_race.rs:LL:CC
-note: inside `main` at $DIR/stack_pop_race.rs:LL:CC
+note: inside `main`
   --> $DIR/stack_pop_race.rs:LL:CC
    |
 LL |     race(0);
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 7d9302e3e3a..484f703f9c1 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
@@ -11,7 +11,7 @@ LL | | }
    | |_^ the program aborted execution
    |
    = note: inside `nounwind` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
-note: inside `main` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
+note: inside `main`
   --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
    |
 LL |     unsafe { nounwind() }
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 7d9302e3e3a..484f703f9c1 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
@@ -11,7 +11,7 @@ LL | | }
    | |_^ the program aborted execution
    |
    = note: inside `nounwind` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
-note: inside `main` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
+note: inside `main`
   --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
    |
 LL |     unsafe { nounwind() }
diff --git a/src/tools/miri/tests/fail/generator-pinned-moved.stderr b/src/tools/miri/tests/fail/generator-pinned-moved.stderr
index 4f73671a789..80c5794736a 100644
--- a/src/tools/miri/tests/fail/generator-pinned-moved.stderr
+++ b/src/tools/miri/tests/fail/generator-pinned-moved.stderr
@@ -8,13 +8,13 @@ LL |         *num += 1;
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside closure at $DIR/generator-pinned-moved.rs:LL:CC
-note: inside `<GeneratorIteratorAdapter<[static generator@$DIR/generator-pinned-moved.rs:LL:CC]> as std::iter::Iterator>::next` at $DIR/generator-pinned-moved.rs:LL:CC
+note: inside `<GeneratorIteratorAdapter<[static generator@$DIR/generator-pinned-moved.rs:LL:CC]> as std::iter::Iterator>::next`
   --> $DIR/generator-pinned-moved.rs:LL:CC
    |
 LL |         match me.resume(()) {
    |               ^^^^^^^^^^^^^
    = note: inside `<std::boxed::Box<GeneratorIteratorAdapter<[static generator@$DIR/generator-pinned-moved.rs:LL:CC]>> as std::iter::Iterator>::next` at RUSTLIB/alloc/src/boxed.rs:LL:CC
-note: inside `main` at $DIR/generator-pinned-moved.rs:LL:CC
+note: inside `main`
   --> $DIR/generator-pinned-moved.rs:LL:CC
    |
 LL |     generator_iterator_2.next(); // and use moved value
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr b/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr
index 36bb9643b48..5c73c76a161 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr
@@ -8,7 +8,7 @@ LL |         unsafe { intrinsics::simd_cast(self) }
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `std::simd::Simd::<f32, 2>::to_int_unchecked::<i32>` at RUSTLIB/core/src/../../portable-simd/crates/core_simd/src/vector.rs:LL:CC
-note: inside `main` at $DIR/simd-float-to-int.rs:LL:CC
+note: inside `main`
   --> $DIR/simd-float-to-int.rs:LL:CC
    |
 LL |         let _x: i32x2 = f32x2::from_array([f32::MAX, f32::MIN]).to_int_unchecked();
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-gather.stderr b/src/tools/miri/tests/fail/intrinsics/simd-gather.stderr
index 29a4ef65705..7512d57f672 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-gather.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/simd-gather.stderr
@@ -8,7 +8,7 @@ LL |         unsafe { intrinsics::simd_gather(or, ptrs, enable.to_int()) }
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `std::simd::Simd::<i8, 4>::gather_select_unchecked` at RUSTLIB/core/src/../../portable-simd/crates/core_simd/src/vector.rs:LL:CC
-note: inside `main` at $DIR/simd-gather.rs:LL:CC
+note: inside `main`
   --> $DIR/simd-gather.rs:LL:CC
    |
 LL |         let _result = Simd::gather_select_unchecked(&vec, Mask::splat(true), idxs, Simd::splat(0));
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr b/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr
index fde85a63503..a9ad60a0e5b 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr
@@ -8,7 +8,7 @@ LL |             intrinsics::simd_scatter(self, ptrs, enable.to_int())
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `std::simd::Simd::<i8, 4>::scatter_select_unchecked` at RUSTLIB/core/src/../../portable-simd/crates/core_simd/src/vector.rs:LL:CC
-note: inside `main` at $DIR/simd-scatter.rs:LL:CC
+note: inside `main`
   --> $DIR/simd-scatter.rs:LL:CC
    |
 LL | /         Simd::from_array([-27, 82, -41, 124]).scatter_select_unchecked(
diff --git a/src/tools/miri/tests/fail/issue-miri-1112.stderr b/src/tools/miri/tests/fail/issue-miri-1112.stderr
index e6644a72849..f1cb50ab9be 100644
--- a/src/tools/miri/tests/fail/issue-miri-1112.stderr
+++ b/src/tools/miri/tests/fail/issue-miri-1112.stderr
@@ -8,7 +8,7 @@ LL |         let obj = std::mem::transmute::<FatPointer, *mut FunnyPointer>(obj)
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `FunnyPointer::from_data_ptr` at $DIR/issue-miri-1112.rs:LL:CC
-note: inside `main` at $DIR/issue-miri-1112.rs:LL:CC
+note: inside `main`
   --> $DIR/issue-miri-1112.rs:LL:CC
    |
 LL |         let _raw: &FunnyPointer = FunnyPointer::from_data_ptr(&hello, &meta as *const _);
diff --git a/src/tools/miri/tests/fail/never_transmute_void.stderr b/src/tools/miri/tests/fail/never_transmute_void.stderr
index 4c3a3d075f0..413172b2546 100644
--- a/src/tools/miri/tests/fail/never_transmute_void.stderr
+++ b/src/tools/miri/tests/fail/never_transmute_void.stderr
@@ -8,7 +8,7 @@ LL |         match v.0 {}
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `m::f` at $DIR/never_transmute_void.rs:LL:CC
-note: inside `main` at $DIR/never_transmute_void.rs:LL:CC
+note: inside `main`
   --> $DIR/never_transmute_void.rs:LL:CC
    |
 LL |     m::f(v);
diff --git a/src/tools/miri/tests/fail/panic/bad_unwind.stderr b/src/tools/miri/tests/fail/panic/bad_unwind.stderr
index 23c33f5e7f3..5d7f01f4786 100644
--- a/src/tools/miri/tests/fail/panic/bad_unwind.stderr
+++ b/src/tools/miri/tests/fail/panic/bad_unwind.stderr
@@ -13,7 +13,7 @@ LL |     std::panic::catch_unwind(|| unwind()).unwrap_err();
    = note: inside `std::panicking::r#try::do_call::<[closure@$DIR/bad_unwind.rs:LL:CC], ()>` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::panicking::r#try::<(), [closure@$DIR/bad_unwind.rs:LL:CC]>` at RUSTLIB/std/src/panicking.rs:LL:CC
    = note: inside `std::panic::catch_unwind::<[closure@$DIR/bad_unwind.rs:LL:CC], ()>` at RUSTLIB/std/src/panic.rs:LL:CC
-note: inside `main` at $DIR/bad_unwind.rs:LL:CC
+note: inside `main`
   --> $DIR/bad_unwind.rs:LL:CC
    |
 LL |     std::panic::catch_unwind(|| unwind()).unwrap_err();
diff --git a/src/tools/miri/tests/fail/panic/double_panic.stderr b/src/tools/miri/tests/fail/panic/double_panic.stderr
index f1d2b4de97c..6bf13f21601 100644
--- a/src/tools/miri/tests/fail/panic/double_panic.stderr
+++ b/src/tools/miri/tests/fail/panic/double_panic.stderr
@@ -75,13 +75,13 @@ LL |     ABORT();
    = 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::rt::begin_panic<&str>::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
-note: inside `<Foo as std::ops::Drop>::drop` at RUSTLIB/std/src/panic.rs:LL:CC
+note: inside `<Foo as std::ops::Drop>::drop`
   --> $DIR/double_panic.rs:LL:CC
    |
 LL |         panic!("second");
    | ^
    = note: inside `std::ptr::drop_in_place::<Foo> - shim(Some(Foo))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
-note: inside `main` at $DIR/double_panic.rs:LL:CC
+note: inside `main`
   --> $DIR/double_panic.rs:LL:CC
    |
 LL | }
diff --git a/src/tools/miri/tests/fail/panic/no_std.stderr b/src/tools/miri/tests/fail/panic/no_std.stderr
index 568b286e1d3..39ad0d268b9 100644
--- a/src/tools/miri/tests/fail/panic/no_std.stderr
+++ b/src/tools/miri/tests/fail/panic/no_std.stderr
@@ -6,7 +6,7 @@ LL |     core::intrinsics::abort();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ the program aborted execution
    |
    = note: inside `panic_handler` at $DIR/no_std.rs:LL:CC
-note: inside `start` at RUSTLIB/core/src/panic.rs:LL:CC
+note: inside `start`
   --> $DIR/no_std.rs:LL:CC
    |
 LL |     panic!("blarg I am dead")
diff --git a/src/tools/miri/tests/fail/panic/panic_abort1.stderr b/src/tools/miri/tests/fail/panic/panic_abort1.stderr
index 75471994546..d25dd7be635 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort1.stderr
+++ b/src/tools/miri/tests/fail/panic/panic_abort1.stderr
@@ -12,7 +12,7 @@ LL |                 ABORT();
    = 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::rt::begin_panic<&str>::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
-note: inside `main` at RUSTLIB/std/src/panic.rs:LL:CC
+note: inside `main`
   --> $DIR/panic_abort1.rs:LL:CC
    |
 LL |     std::panic!("panicking from libstd");
diff --git a/src/tools/miri/tests/fail/panic/panic_abort2.stderr b/src/tools/miri/tests/fail/panic/panic_abort2.stderr
index 2fdf889d798..f56d509a697 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort2.stderr
+++ b/src/tools/miri/tests/fail/panic/panic_abort2.stderr
@@ -13,7 +13,7 @@ LL |                 ABORT();
    = 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 `main` at RUSTLIB/std/src/panic.rs:LL:CC
+note: inside `main`
   --> $DIR/panic_abort2.rs:LL:CC
    |
 LL |     std::panic!("{}-panicking from libstd", 42);
diff --git a/src/tools/miri/tests/fail/panic/panic_abort3.stderr b/src/tools/miri/tests/fail/panic/panic_abort3.stderr
index 8704b0d940b..43792f76993 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort3.stderr
+++ b/src/tools/miri/tests/fail/panic/panic_abort3.stderr
@@ -13,7 +13,7 @@ LL |                 ABORT();
    = 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 `main` at RUSTLIB/core/src/panic.rs:LL:CC
+note: inside `main`
   --> $DIR/panic_abort3.rs:LL:CC
    |
 LL |     core::panic!("panicking from libcore");
diff --git a/src/tools/miri/tests/fail/panic/panic_abort4.stderr b/src/tools/miri/tests/fail/panic/panic_abort4.stderr
index 1d75d72c031..89e181bfb27 100644
--- a/src/tools/miri/tests/fail/panic/panic_abort4.stderr
+++ b/src/tools/miri/tests/fail/panic/panic_abort4.stderr
@@ -13,7 +13,7 @@ LL |                 ABORT();
    = 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 `main` at RUSTLIB/core/src/panic.rs:LL:CC
+note: inside `main`
   --> $DIR/panic_abort4.rs:LL:CC
    |
 LL |     core::panic!("{}-panicking from libcore", 42);
diff --git a/src/tools/miri/tests/fail/provenance/provenance_transmute.stderr b/src/tools/miri/tests/fail/provenance/provenance_transmute.stderr
index f7c5f6046e1..042d8cd4afe 100644
--- a/src/tools/miri/tests/fail/provenance/provenance_transmute.stderr
+++ b/src/tools/miri/tests/fail/provenance/provenance_transmute.stderr
@@ -8,7 +8,7 @@ LL |         let _val = *left_ptr;
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `deref` at $DIR/provenance_transmute.rs:LL:CC
-note: inside `main` at $DIR/provenance_transmute.rs:LL:CC
+note: inside `main`
   --> $DIR/provenance_transmute.rs:LL:CC
    |
 LL |         deref(ptr1, ptr2.with_addr(ptr1.addr()));
diff --git a/src/tools/miri/tests/fail/shims/fs/isolated_file.stderr b/src/tools/miri/tests/fail/shims/fs/isolated_file.stderr
index 269b1383aad..2385439c8a5 100644
--- a/src/tools/miri/tests/fail/shims/fs/isolated_file.stderr
+++ b/src/tools/miri/tests/fail/shims/fs/isolated_file.stderr
@@ -17,7 +17,7 @@ LL |         let fd = cvt_r(|| unsafe { open64(path.as_ptr(), flags, opts.mode a
    = note: inside `std::fs::OpenOptions::_open` at RUSTLIB/std/src/fs.rs:LL:CC
    = note: inside `std::fs::OpenOptions::open::<&std::path::Path>` at RUSTLIB/std/src/fs.rs:LL:CC
    = note: inside `std::fs::File::open::<&str>` at RUSTLIB/std/src/fs.rs:LL:CC
-note: inside `main` at $DIR/isolated_file.rs:LL:CC
+note: inside `main`
   --> $DIR/isolated_file.rs:LL:CC
    |
 LL |     let _file = std::fs::File::open("file.txt").unwrap();
diff --git a/src/tools/miri/tests/fail/shims/fs/mkstemp_immutable_arg.stderr b/src/tools/miri/tests/fail/shims/fs/mkstemp_immutable_arg.stderr
index 414ac1cb1b7..35ff1926b06 100644
--- a/src/tools/miri/tests/fail/shims/fs/mkstemp_immutable_arg.stderr
+++ b/src/tools/miri/tests/fail/shims/fs/mkstemp_immutable_arg.stderr
@@ -8,7 +8,7 @@ LL |     let _fd = unsafe { libc::mkstemp(s) };
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `test_mkstemp_immutable_arg` at $DIR/mkstemp_immutable_arg.rs:LL:CC
-note: inside `main` at $DIR/mkstemp_immutable_arg.rs:LL:CC
+note: inside `main`
   --> $DIR/mkstemp_immutable_arg.rs:LL:CC
    |
 LL |     test_mkstemp_immutable_arg();
diff --git a/src/tools/miri/tests/fail/shims/fs/unix_open_missing_required_mode.stderr b/src/tools/miri/tests/fail/shims/fs/unix_open_missing_required_mode.stderr
index 38d033b4945..5a8e7352c76 100644
--- a/src/tools/miri/tests/fail/shims/fs/unix_open_missing_required_mode.stderr
+++ b/src/tools/miri/tests/fail/shims/fs/unix_open_missing_required_mode.stderr
@@ -8,7 +8,7 @@ LL | ...safe { libc::open(name_ptr, libc::O_CREAT) };
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `test_file_open_missing_needed_mode` at $DIR/unix_open_missing_required_mode.rs:LL:CC
-note: inside `main` at $DIR/unix_open_missing_required_mode.rs:LL:CC
+note: inside `main`
   --> $DIR/unix_open_missing_required_mode.rs:LL:CC
    |
 LL |     test_file_open_missing_needed_mode();
diff --git a/src/tools/miri/tests/fail/should-pass/cpp20_rwc_syncs.stderr b/src/tools/miri/tests/fail/should-pass/cpp20_rwc_syncs.stderr
index 8a24b085a99..325565fa1e7 100644
--- a/src/tools/miri/tests/fail/should-pass/cpp20_rwc_syncs.stderr
+++ b/src/tools/miri/tests/fail/should-pass/cpp20_rwc_syncs.stderr
@@ -8,7 +8,7 @@ LL |             std::hint::unreachable_unchecked();
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `test_cpp20_rwc_syncs` at $DIR/cpp20_rwc_syncs.rs:LL:CC
-note: inside `main` at $DIR/cpp20_rwc_syncs.rs:LL:CC
+note: inside `main`
   --> $DIR/cpp20_rwc_syncs.rs:LL:CC
    |
 LL |         test_cpp20_rwc_syncs();
diff --git a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut1.stderr b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut1.stderr
index 268d253ad5b..4514abb4ab2 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut1.stderr
@@ -18,7 +18,7 @@ LL | pub fn safe(_x: &mut i32, _y: &mut i32) {}
    |             ^^
    = note: BACKTRACE:
    = note: inside `safe` at $DIR/aliasing_mut1.rs:LL:CC
-note: inside `main` at $DIR/aliasing_mut1.rs:LL:CC
+note: inside `main`
   --> $DIR/aliasing_mut1.rs:LL:CC
    |
 LL |     safe_raw(xraw, xraw);
diff --git a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut2.stderr b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut2.stderr
index 77a542f45a2..9ca9743cbd9 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut2.stderr
@@ -18,7 +18,7 @@ LL | pub fn safe(_x: &i32, _y: &mut i32) {}
    |             ^^
    = note: BACKTRACE:
    = note: inside `safe` at $DIR/aliasing_mut2.rs:LL:CC
-note: inside `main` at $DIR/aliasing_mut2.rs:LL:CC
+note: inside `main`
   --> $DIR/aliasing_mut2.rs:LL:CC
    |
 LL |     safe_raw(xshr, xraw);
diff --git a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut3.stderr b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut3.stderr
index eb6b01fc6b1..b504097a3c9 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut3.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut3.stderr
@@ -21,7 +21,7 @@ LL |     safe_raw(xraw, xshr);
    |     ^^^^^^^^^^^^^^^^^^^^
    = note: BACKTRACE:
    = note: inside `safe` at $DIR/aliasing_mut3.rs:LL:CC
-note: inside `main` at $DIR/aliasing_mut3.rs:LL:CC
+note: inside `main`
   --> $DIR/aliasing_mut3.rs:LL:CC
    |
 LL |     safe_raw(xraw, xshr);
diff --git a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut4.stderr b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut4.stderr
index e592b154a73..6fe0d709029 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut4.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/aliasing_mut4.stderr
@@ -18,7 +18,7 @@ LL | pub fn safe(_x: &i32, _y: &mut Cell<i32>) {}
    |             ^^
    = note: BACKTRACE:
    = note: inside `safe` at $DIR/aliasing_mut4.rs:LL:CC
-note: inside `main` at $DIR/aliasing_mut4.rs:LL:CC
+note: inside `main`
   --> $DIR/aliasing_mut4.rs:LL:CC
    |
 LL |     safe_raw(xshr, xraw as *mut _);
diff --git a/src/tools/miri/tests/fail/stacked_borrows/box_exclusive_violation1.stderr b/src/tools/miri/tests/fail/stacked_borrows/box_exclusive_violation1.stderr
index d82b8342f12..f114130f6fa 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/box_exclusive_violation1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/box_exclusive_violation1.stderr
@@ -21,12 +21,12 @@ LL |     *our = 5;
    |     ^^^^^^^^
    = note: BACKTRACE:
    = note: inside `unknown_code_2` at $DIR/box_exclusive_violation1.rs:LL:CC
-note: inside `demo_box_advanced_unique` at $DIR/box_exclusive_violation1.rs:LL:CC
+note: inside `demo_box_advanced_unique`
   --> $DIR/box_exclusive_violation1.rs:LL:CC
    |
 LL |     unknown_code_2();
    |     ^^^^^^^^^^^^^^^^
-note: inside `main` at $DIR/box_exclusive_violation1.rs:LL:CC
+note: inside `main`
   --> $DIR/box_exclusive_violation1.rs:LL:CC
    |
 LL |     demo_box_advanced_unique(Box::new(0));
diff --git a/src/tools/miri/tests/fail/stacked_borrows/box_noalias_violation.stderr b/src/tools/miri/tests/fail/stacked_borrows/box_noalias_violation.stderr
index 3c84cbcfd51..139fcd0ca45 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/box_noalias_violation.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/box_noalias_violation.stderr
@@ -18,7 +18,7 @@ LL | unsafe fn test(mut x: Box<i32>, y: *const i32) -> i32 {
    |                ^^^^^
    = note: BACKTRACE:
    = note: inside `test` at $DIR/box_noalias_violation.rs:LL:CC
-note: inside `main` at $DIR/box_noalias_violation.rs:LL:CC
+note: inside `main`
   --> $DIR/box_noalias_violation.rs:LL:CC
    |
 LL |         test(Box::from_raw(ptr), ptr);
diff --git a/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.stderr b/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.stderr
index bb3eaec1e85..516964b9a4e 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector1.stderr
@@ -12,18 +12,18 @@ LL |     unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
    = note: inside `alloc::alloc::box_free::<i32, std::alloc::Global>` at RUSTLIB/alloc/src/alloc.rs:LL:CC
    = note: inside `std::ptr::drop_in_place::<std::boxed::Box<i32>> - shim(Some(std::boxed::Box<i32>))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
    = note: inside `std::mem::drop::<std::boxed::Box<i32>>` at RUSTLIB/core/src/mem/mod.rs:LL:CC
-note: inside closure at $DIR/deallocate_against_protector1.rs:LL:CC
+note: inside closure
   --> $DIR/deallocate_against_protector1.rs:LL:CC
    |
 LL |         drop(unsafe { Box::from_raw(raw) });
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: inside `<[closure@$DIR/deallocate_against_protector1.rs:LL:CC] as std::ops::FnOnce<(&mut i32,)>>::call_once - shim` at RUSTLIB/core/src/ops/function.rs:LL:CC
-note: inside `inner` at $DIR/deallocate_against_protector1.rs:LL:CC
+note: inside `inner`
   --> $DIR/deallocate_against_protector1.rs:LL:CC
    |
 LL |     f(x)
    |     ^^^^
-note: inside `main` at $DIR/deallocate_against_protector1.rs:LL:CC
+note: inside `main`
   --> $DIR/deallocate_against_protector1.rs:LL:CC
    |
 LL | /     inner(Box::leak(Box::new(0)), |x| {
diff --git a/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector2.stderr b/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector2.stderr
index 25bab1aa564..47cfa0de725 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/deallocate_against_protector2.stderr
@@ -12,18 +12,18 @@ LL |     unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
    = note: inside `alloc::alloc::box_free::<NotUnpin, std::alloc::Global>` at RUSTLIB/alloc/src/alloc.rs:LL:CC
    = note: inside `std::ptr::drop_in_place::<std::boxed::Box<NotUnpin>> - shim(Some(std::boxed::Box<NotUnpin>))` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
    = note: inside `std::mem::drop::<std::boxed::Box<NotUnpin>>` at RUSTLIB/core/src/mem/mod.rs:LL:CC
-note: inside closure at $DIR/deallocate_against_protector2.rs:LL:CC
+note: inside closure
   --> $DIR/deallocate_against_protector2.rs:LL:CC
    |
 LL |         drop(unsafe { Box::from_raw(raw) });
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: inside `<[closure@$DIR/deallocate_against_protector2.rs:LL:CC] as std::ops::FnOnce<(&mut NotUnpin,)>>::call_once - shim` at RUSTLIB/core/src/ops/function.rs:LL:CC
-note: inside `inner` at $DIR/deallocate_against_protector2.rs:LL:CC
+note: inside `inner`
   --> $DIR/deallocate_against_protector2.rs:LL:CC
    |
 LL |     f(x)
    |     ^^^^
-note: inside `main` at $DIR/deallocate_against_protector2.rs:LL:CC
+note: inside `main`
   --> $DIR/deallocate_against_protector2.rs:LL:CC
    |
 LL | /     inner(Box::leak(Box::new(NotUnpin(0, PhantomPinned))), |x| {
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr
index 3b7802901a5..f2f13d0d559 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_dealloc1.stderr
@@ -18,7 +18,7 @@ LL |         ptr1.write(0);
    |         ^^^^^^^^^^^^^
    = note: BACKTRACE:
    = note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
-note: inside `main` at $DIR/illegal_deALLOC.rs:LL:CC
+note: inside `main`
   --> $DIR/illegal_deALLOC.rs:LL:CC
    |
 LL |         dealloc(ptr2, Layout::from_size_align_unchecked(1, 1));
diff --git a/src/tools/miri/tests/fail/stacked_borrows/illegal_write6.stderr b/src/tools/miri/tests/fail/stacked_borrows/illegal_write6.stderr
index 1a627b8a883..49d9050f309 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/illegal_write6.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/illegal_write6.stderr
@@ -18,7 +18,7 @@ LL | fn foo(a: &mut u32, y: *mut u32) -> u32 {
    |        ^
    = note: BACKTRACE:
    = note: inside `foo` at $DIR/illegal_write6.rs:LL:CC
-note: inside `main` at $DIR/illegal_write6.rs:LL:CC
+note: inside `main`
   --> $DIR/illegal_write6.rs:LL:CC
    |
 LL |     foo(x, p);
diff --git a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr
index 1ef36b7ac10..a53c633c381 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector1.stderr
@@ -18,7 +18,7 @@ LL | fn inner(x: *mut i32, _y: &mut i32) {
    |                       ^^
    = note: BACKTRACE:
    = note: inside `inner` at $DIR/invalidate_against_protector1.rs:LL:CC
-note: inside `main` at $DIR/invalidate_against_protector1.rs:LL:CC
+note: inside `main`
   --> $DIR/invalidate_against_protector1.rs:LL:CC
    |
 LL |     inner(xraw, xref);
diff --git a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector2.stderr b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector2.stderr
index 941b936e5d7..6ee78d1aac6 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector2.stderr
@@ -18,7 +18,7 @@ LL | fn inner(x: *mut i32, _y: &i32) {
    |                       ^^
    = note: BACKTRACE:
    = note: inside `inner` at $DIR/invalidate_against_protector2.rs:LL:CC
-note: inside `main` at $DIR/invalidate_against_protector2.rs:LL:CC
+note: inside `main`
   --> $DIR/invalidate_against_protector2.rs:LL:CC
    |
 LL |     inner(xraw, xref);
diff --git a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector3.stderr b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector3.stderr
index 176a859ee8a..2b38dea9dbb 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector3.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/invalidate_against_protector3.stderr
@@ -18,7 +18,7 @@ LL | fn inner(x: *mut i32, _y: &i32) {
    |                       ^^
    = note: BACKTRACE:
    = note: inside `inner` at $DIR/invalidate_against_protector3.rs:LL:CC
-note: inside `main` at $DIR/invalidate_against_protector3.rs:LL:CC
+note: inside `main`
   --> $DIR/invalidate_against_protector3.rs:LL:CC
    |
 LL |         inner(ptr, &*ptr);
diff --git a/src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-1.stderr b/src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-1.stderr
index 16c8810a8e6..c69a3af293c 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-1.stderr
@@ -9,7 +9,7 @@ LL |         Box(unsafe { Unique::new_unchecked(raw) }, alloc)
    = note: BACKTRACE:
    = note: inside `std::boxed::Box::<u32>::from_raw_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
    = note: inside `std::boxed::Box::<u32>::from_raw` at RUSTLIB/alloc/src/boxed.rs:LL:CC
-note: inside `main` at $DIR/issue-miri-1050-1.rs:LL:CC
+note: inside `main`
   --> $DIR/issue-miri-1050-1.rs:LL:CC
    |
 LL |         drop(Box::from_raw(ptr as *mut u32));
diff --git a/src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-2.stderr b/src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-2.stderr
index d57e7662e50..23d7fdcd03b 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-2.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/issue-miri-1050-2.stderr
@@ -9,7 +9,7 @@ LL |         Box(unsafe { Unique::new_unchecked(raw) }, alloc)
    = note: BACKTRACE:
    = note: inside `std::boxed::Box::<i32>::from_raw_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
    = note: inside `std::boxed::Box::<i32>::from_raw` at RUSTLIB/alloc/src/boxed.rs:LL:CC
-note: inside `main` at $DIR/issue-miri-1050-2.rs:LL:CC
+note: inside `main`
   --> $DIR/issue-miri-1050-2.rs:LL:CC
    |
 LL |         drop(Box::from_raw(ptr.as_ptr()));
diff --git a/src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation1.stderr b/src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation1.stderr
index 1c7f8e12d3d..2f3900c40d7 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/mut_exclusive_violation1.stderr
@@ -21,12 +21,12 @@ LL |     *our = 5;
    |     ^^^^^^^^
    = note: BACKTRACE:
    = note: inside `unknown_code_2` at $DIR/mut_exclusive_violation1.rs:LL:CC
-note: inside `demo_mut_advanced_unique` at $DIR/mut_exclusive_violation1.rs:LL:CC
+note: inside `demo_mut_advanced_unique`
   --> $DIR/mut_exclusive_violation1.rs:LL:CC
    |
 LL |     unknown_code_2();
    |     ^^^^^^^^^^^^^^^^
-note: inside `main` at $DIR/mut_exclusive_violation1.rs:LL:CC
+note: inside `main`
   --> $DIR/mut_exclusive_violation1.rs:LL:CC
    |
 LL |     demo_mut_advanced_unique(&mut 0);
diff --git a/src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.stderr b/src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.stderr
index 70186dd3a53..90677dfaf55 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/newtype_pair_retagging.stderr
@@ -19,17 +19,17 @@ LL | fn dealloc_while_running(_n: Newtype<'_>, dealloc: impl FnOnce()) {
    = note: BACKTRACE:
    = note: inside `std::boxed::Box::<i32>::from_raw_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
    = note: inside `std::boxed::Box::<i32>::from_raw` at RUSTLIB/alloc/src/boxed.rs:LL:CC
-note: inside closure at $DIR/newtype_pair_retagging.rs:LL:CC
+note: inside closure
   --> $DIR/newtype_pair_retagging.rs:LL:CC
    |
 LL |             || drop(Box::from_raw(ptr)),
    |                     ^^^^^^^^^^^^^^^^^^
-note: inside `dealloc_while_running::<[closure@$DIR/newtype_pair_retagging.rs:LL:CC]>` at $DIR/newtype_pair_retagging.rs:LL:CC
+note: inside `dealloc_while_running::<[closure@$DIR/newtype_pair_retagging.rs:LL:CC]>`
   --> $DIR/newtype_pair_retagging.rs:LL:CC
    |
 LL |     dealloc();
    |     ^^^^^^^^^
-note: inside `main` at $DIR/newtype_pair_retagging.rs:LL:CC
+note: inside `main`
   --> $DIR/newtype_pair_retagging.rs:LL:CC
    |
 LL | /         dealloc_while_running(
diff --git a/src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.stderr b/src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.stderr
index 69fa27c9c09..f189d0483d1 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/newtype_retagging.stderr
@@ -19,17 +19,17 @@ LL | fn dealloc_while_running(_n: Newtype<'_>, dealloc: impl FnOnce()) {
    = note: BACKTRACE:
    = note: inside `std::boxed::Box::<i32>::from_raw_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
    = note: inside `std::boxed::Box::<i32>::from_raw` at RUSTLIB/alloc/src/boxed.rs:LL:CC
-note: inside closure at $DIR/newtype_retagging.rs:LL:CC
+note: inside closure
   --> $DIR/newtype_retagging.rs:LL:CC
    |
 LL |             || drop(Box::from_raw(ptr)),
    |                     ^^^^^^^^^^^^^^^^^^
-note: inside `dealloc_while_running::<[closure@$DIR/newtype_retagging.rs:LL:CC]>` at $DIR/newtype_retagging.rs:LL:CC
+note: inside `dealloc_while_running::<[closure@$DIR/newtype_retagging.rs:LL:CC]>`
   --> $DIR/newtype_retagging.rs:LL:CC
    |
 LL |     dealloc();
    |     ^^^^^^^^^
-note: inside `main` at $DIR/newtype_retagging.rs:LL:CC
+note: inside `main`
   --> $DIR/newtype_retagging.rs:LL:CC
    |
 LL | /         dealloc_while_running(
diff --git a/src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr b/src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr
index 6415af1e18b..7d58d1aebbe 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/pointer_smuggling.stderr
@@ -21,7 +21,7 @@ LL |     *val = 2; // this invalidates any raw ptrs `fun1` might have created.
    |     ^^^^^^^^
    = note: BACKTRACE:
    = note: inside `fun2` at $DIR/pointer_smuggling.rs:LL:CC
-note: inside `main` at $DIR/pointer_smuggling.rs:LL:CC
+note: inside `main`
   --> $DIR/pointer_smuggling.rs:LL:CC
    |
 LL |     fun2(); // if they now use a raw ptr they break our reference
diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr
index f25d689524d..5dc936f0707 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_read.stderr
@@ -8,7 +8,7 @@ LL |         *p = 5;
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `thread_2` at $DIR/retag_data_race_read.rs:LL:CC
-note: inside closure at $DIR/retag_data_race_read.rs:LL:CC
+note: inside closure
   --> $DIR/retag_data_race_read.rs:LL:CC
    |
 LL |     let t2 = std::thread::spawn(move || thread_2(p));
diff --git a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.stderr b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.stderr
index f97e6bb11e9..03c24503564 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/retag_data_race_write.stderr
@@ -8,7 +8,7 @@ LL |         *p = 5;
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
    = note: BACKTRACE:
    = note: inside `thread_2` at $DIR/retag_data_race_write.rs:LL:CC
-note: inside closure at $DIR/retag_data_race_write.rs:LL:CC
+note: inside closure
   --> $DIR/retag_data_race_write.rs:LL:CC
    |
 LL |     let t2 = std::thread::spawn(move || thread_2(p));
diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut.stderr
index 9deb0c41742..1b28f780c1c 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut.stderr
@@ -21,7 +21,7 @@ LL |     let _val = unsafe { *xraw }; // invalidate xref
    |                         ^^^^^
    = note: BACKTRACE:
    = note: inside `foo` at $DIR/return_invalid_mut.rs:LL:CC
-note: inside `main` at $DIR/return_invalid_mut.rs:LL:CC
+note: inside `main`
   --> $DIR/return_invalid_mut.rs:LL:CC
    |
 LL |     foo(&mut (1, 2));
diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr
index c0ff35ebcde..db14dcafa00 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_option.stderr
@@ -21,7 +21,7 @@ LL |     let _val = unsafe { *xraw }; // invalidate xref
    |                         ^^^^^
    = note: BACKTRACE:
    = note: inside `foo` at $DIR/return_invalid_mut_option.rs:LL:CC
-note: inside `main` at $DIR/return_invalid_mut_option.rs:LL:CC
+note: inside `main`
   --> $DIR/return_invalid_mut_option.rs:LL:CC
    |
 LL |     match foo(&mut (1, 2)) {
diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr
index 9abf43c29f0..81ed4218aad 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_mut_tuple.stderr
@@ -21,7 +21,7 @@ LL |     let _val = unsafe { *xraw }; // invalidate xref
    |                         ^^^^^
    = note: BACKTRACE:
    = note: inside `foo` at $DIR/return_invalid_mut_tuple.rs:LL:CC
-note: inside `main` at $DIR/return_invalid_mut_tuple.rs:LL:CC
+note: inside `main`
   --> $DIR/return_invalid_mut_tuple.rs:LL:CC
    |
 LL |     foo(&mut (1, 2)).0;
diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr.stderr
index dd651517c2f..9c8cc50b2d7 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr.stderr
@@ -21,7 +21,7 @@ LL |     unsafe { *xraw = (42, 23) }; // unfreeze
    |              ^^^^^^^^^^^^^^^^
    = note: BACKTRACE:
    = note: inside `foo` at $DIR/return_invalid_shr.rs:LL:CC
-note: inside `main` at $DIR/return_invalid_shr.rs:LL:CC
+note: inside `main`
   --> $DIR/return_invalid_shr.rs:LL:CC
    |
 LL |     foo(&mut (1, 2));
diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.stderr
index 6066bf89f5d..00ce6f6cd5f 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_option.stderr
@@ -21,7 +21,7 @@ LL |     unsafe { *xraw = (42, 23) }; // unfreeze
    |              ^^^^^^^^^^^^^^^^
    = note: BACKTRACE:
    = note: inside `foo` at $DIR/return_invalid_shr_option.rs:LL:CC
-note: inside `main` at $DIR/return_invalid_shr_option.rs:LL:CC
+note: inside `main`
   --> $DIR/return_invalid_shr_option.rs:LL:CC
    |
 LL |     match foo(&mut (1, 2)) {
diff --git a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr
index 52d365246a7..bbd17b1284c 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/return_invalid_shr_tuple.stderr
@@ -21,7 +21,7 @@ LL |     unsafe { *xraw = (42, 23) }; // unfreeze
    |              ^^^^^^^^^^^^^^^^
    = note: BACKTRACE:
    = note: inside `foo` at $DIR/return_invalid_shr_tuple.rs:LL:CC
-note: inside `main` at $DIR/return_invalid_shr_tuple.rs:LL:CC
+note: inside `main`
   --> $DIR/return_invalid_shr_tuple.rs:LL:CC
    |
 LL |     foo(&mut (1, 2)).0;
diff --git a/src/tools/miri/tests/fail/stacked_borrows/shr_frozen_violation1.stderr b/src/tools/miri/tests/fail/stacked_borrows/shr_frozen_violation1.stderr
index 0818d07da48..fe0ac211318 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/shr_frozen_violation1.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/shr_frozen_violation1.stderr
@@ -16,12 +16,12 @@ LL |         *(x as *const i32 as *mut i32) = 7;
    |           ^
    = note: BACKTRACE:
    = note: inside `unknown_code` at $DIR/shr_frozen_violation1.rs:LL:CC
-note: inside `foo` at $DIR/shr_frozen_violation1.rs:LL:CC
+note: inside `foo`
   --> $DIR/shr_frozen_violation1.rs:LL:CC
    |
 LL |     unknown_code(&*x);
    |     ^^^^^^^^^^^^^^^^^
-note: inside `main` at $DIR/shr_frozen_violation1.rs:LL:CC
+note: inside `main`
   --> $DIR/shr_frozen_violation1.rs:LL:CC
    |
 LL |     println!("{}", foo(&mut 0));
diff --git a/src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr b/src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr
index 86f1da1f70a..e134ee2845d 100644
--- a/src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr
+++ b/src/tools/miri/tests/fail/stacked_borrows/zst_slice.stderr
@@ -16,7 +16,7 @@ LL |         assert_eq!(*s.get_unchecked(1), 2);
    |                     ^^^^^^^^^^^^^^^^^^
    = note: BACKTRACE:
    = note: inside `core::slice::<impl [i32]>::get_unchecked::<usize>` at RUSTLIB/core/src/slice/mod.rs:LL:CC
-note: inside `main` at $DIR/zst_slice.rs:LL:CC
+note: inside `main`
   --> $DIR/zst_slice.rs:LL:CC
    |
 LL |         assert_eq!(*s.get_unchecked(1), 2);
diff --git a/src/tools/miri/tests/fail/uninit_buffer.stderr b/src/tools/miri/tests/fail/uninit_buffer.stderr
index a543d59addb..8da532cfff0 100644
--- a/src/tools/miri/tests/fail/uninit_buffer.stderr
+++ b/src/tools/miri/tests/fail/uninit_buffer.stderr
@@ -9,7 +9,7 @@ LL |         let mut order = unsafe { memcmp(left.as_ptr(), right.as_ptr(), len)
    = note: BACKTRACE:
    = note: inside `<u8 as core::slice::cmp::SliceOrd>::compare` at RUSTLIB/core/src/slice/cmp.rs:LL:CC
    = note: inside `core::slice::cmp::<impl std::cmp::Ord for [u8]>::cmp` at RUSTLIB/core/src/slice/cmp.rs:LL:CC
-note: inside `main` at $DIR/uninit_buffer.rs:LL:CC
+note: inside `main`
   --> $DIR/uninit_buffer.rs:LL:CC
    |
 LL |         drop(slice1.cmp(slice2));
diff --git a/src/tools/miri/tests/fail/uninit_buffer_with_provenance.stderr b/src/tools/miri/tests/fail/uninit_buffer_with_provenance.stderr
index 715d76aa1c2..210fc8e109a 100644
--- a/src/tools/miri/tests/fail/uninit_buffer_with_provenance.stderr
+++ b/src/tools/miri/tests/fail/uninit_buffer_with_provenance.stderr
@@ -9,7 +9,7 @@ LL |         let mut order = unsafe { memcmp(left.as_ptr(), right.as_ptr(), len)
    = note: BACKTRACE:
    = note: inside `<u8 as core::slice::cmp::SliceOrd>::compare` at RUSTLIB/core/src/slice/cmp.rs:LL:CC
    = note: inside `core::slice::cmp::<impl std::cmp::Ord for [u8]>::cmp` at RUSTLIB/core/src/slice/cmp.rs:LL:CC
-note: inside `main` at $DIR/uninit_buffer_with_provenance.rs:LL:CC
+note: inside `main`
   --> $DIR/uninit_buffer_with_provenance.rs:LL:CC
    |
 LL |         drop(slice1.cmp(slice2));
diff --git a/src/tools/miri/tests/pass/box.stderr b/src/tools/miri/tests/pass/box.stderr
index 0001a8dd6eb..4c2fb40e110 100644
--- a/src/tools/miri/tests/pass/box.stderr
+++ b/src/tools/miri/tests/pass/box.stderr
@@ -12,7 +12,7 @@ LL |         let r2 = ((r as usize) + 0) as *mut i32;
    = help: Alternatively, the `-Zmiri-permissive-provenance` flag disables this warning.
    = note: BACKTRACE:
    = note: inside `into_raw` at $DIR/box.rs:LL:CC
-note: inside `main` at $DIR/box.rs:LL:CC
+note: inside `main`
   --> $DIR/box.rs:LL:CC
    |
 LL |     into_raw();
@@ -25,7 +25,7 @@ LL |         let r = ((u.as_ptr() as usize) + 0) as *mut i32;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ integer-to-pointer cast
    |
    = note: inside `into_unique` at $DIR/box.rs:LL:CC
-note: inside `main` at $DIR/box.rs:LL:CC
+note: inside `main`
   --> $DIR/box.rs:LL:CC
    |
 LL |     into_unique();
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index ff7a219d9bd..7ee8c5d3bad 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -219,6 +219,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "snap",
     "stable_deref_trait",
     "stacker",
+    "static_assertions",
     "syn",
     "synstructure",
     "tempfile",
@@ -239,6 +240,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "tracing-log",
     "tracing-subscriber",
     "tracing-tree",
+    "twox-hash",
     "type-map",
     "typenum",
     "unic-char-property",
diff --git a/src/version b/src/version
index 65ee0959841..ee2f4ca9130 100644
--- a/src/version
+++ b/src/version
@@ -1 +1 @@
-1.67.0
+1.68.0